stack2
stack2

Reputation: 31

How to get counts using the `IN` operator

I am trying to use the IN operator to get the count of certain fields in the table.

This is my query:

SELECT order_id, COUNT(*)
FROM remake_error_type
WHERE order_id IN (1, 2, 100)
GROUP BY order_id;

My current output:

| order_id | COUNT(*) |
+----------+----------+
|    1     |    8     |
|    2     |    8     |

My expected output:

| order_id | COUNT(*) |
+----------+----------+
|    1     |    8     |
|    2     |    8     |
|    100   |    0     |

Upvotes: 3

Views: 66

Answers (3)

Haleemur Ali
Haleemur Ali

Reputation: 28243

You can create a temporary table, insert as many order_ids as required, and perform the left join to remake_error_type. At a small number of orders the other answers are sufficient, but if you were doing this for a lot of orders, UNION ALL and sub-queries are inefficient, both to type it up and to execute on the server.

Additionally, this is a very dynamic approach, because you can control easily the values in your temp table by modifying the insert statement.

However, this will only work if the database user has sufficient privileges: at least select, create temporary and drop table.

DROP TABLE IF EXISTS myTempOrders;
CREATE TEMPORARY TABLE myTempOrders (order_id INTEGER, PRIMARY KEY(order_id));
INSERT INTO myTempOrders (order_id) VALUES (1), (2), (100);

SELECT temp.order_id, count(*)

FROM myTempOrders temp
LEFT JOIN remake_error_type ON temp.order_id = remake_error_type.order_id
GROUP BY 1

If the order_id values exist in some table, then it is possible to extract the desired result without creating a temporary table and inserting values into it.

To qualify, the table must

  • have an auto increment primary key with # rows greater than the maximum sought order_id value
  • have a starting increment value less than the minimum sought order_id value
  • have no missing values in the primary key (i.e. no records have been deleted)

if a qualified table exists, then you can run the following query, where you have to replace surrogate with the qualified table name and surrogate_id with the auto-incrementing primary key of the qualified table name

SELECT surrogate.surrogate_id, count(*)

FROM my_qualified_table surrogate
LEFT JOIN remake_error_type ON surrogate.surrogate_id = remake_error_type.order_id
WHERE surrogate.surrogate_id IN (1, 2, 100)
GROUP BY 1

Upvotes: 1

AdamMc331
AdamMc331

Reputation: 16691

You could use a union for this. No, this does not use the IN operator, but it is an alternative that will give you your expected results. One option is to hardcode the order_id and use conditional aggregation to get the SUM() of rows with that id:

SELECT 1 AS order_id, SUM(order_id = 1) AS numOrders FROM myTable
UNION ALL
SELECT 2 AS order_id, SUM(order_id = 2) AS numOrders FROM myTable
UNION ALL
SELECT 100 AS order_id, SUM(order_id = 100) AS numOrders FROM myTable;

Here is an SQL Fiddle example.

Upvotes: 0

fthiella
fthiella

Reputation: 49049

You can write your query this way:

SELECT t.id, COUNT(remake_error_type.order_id)
FROM
  (SELECT 1 AS id UNION ALL SELECT 2 UNION ALL SELECT 100) as t
  LEFT JOIN remake_error_type
  ON t.id = remake_error_type.order_id
GROUP BY
  t.id

a LEFT JOIN will return all rows from the subquery on the left, and the COUNT(remake_error_type.order_id) will count all values where the join succeeds.

Upvotes: 2

Related Questions