mysql подсчитывает строки дочерней таблицы с условием
У меня есть две таблицы: "пользователь" -> "заказ"
ТАБЛИЦА: пользователь
user_id
-----------
u1
u2
ТАБЛИЦА: заказ
order_id | user_id | flag
-------------------------
o1 | u1 | fA
o2 | u2 | fB
Y нужно получить всех пользователей, считая, сколько раз были заказы с флагом 'fA'
РЕЗУЛЬТАТЫ ЧТО МНЕ НУЖНО:
user_id | orders
----------------
u1 | 1
u2 | 0
Я ПОПРОБУЮ:
SELECT
u.user_id,
COUNT(o.order_id) AS orders
FROM
`user` AS u LEFT JOIN
`order` AS o USING (user_id)
WHERE
o.flag IS NULL OR
o.flag IN ('fA')
GROUP BY
u.user_id;
Но этот запрос исключает user=u2, потому что у него нет ордера с флагом fA; Мне нужен пользователь = u2 появляются с заказов =0
Может быть что-то подобное:
SELECT
u.user_id,
COUNT(o.order_id IF o.flag IN('fA')) OR 0 AS count ...
Таблицы и данные:
CREATE TABLE `user` (user_id VARCHAR(2) NULL);
CREATE TABLE `order` (order_id VARCHAR(2) NULL,user_id VARCHAR(2) NULL,flag VARCHAR(2) NULL);
INSERT INTO `user` VALUES ('u1'), ('u2');
INSERT INTO `order` VALUES ('o1','u1','fA'),('o2','u2','fB');
5 ответов
Вы можете попробовать использовать условие в операторе 'ON' 'LEFT JOIN', например:
SELECT u.user_id, COUNT(o.user_id)
FROM user u
LEFT JOIN `order` o ON u.user_id = o.user_id AND o.flag = 'fA'
GROUP BY user_id
Есть как минимум три способа сделать это:
Просто используйте зависимый подзапрос.
SELECT u.user_id, (SELECT count(user_id) FROM `order` o WHERE o.user_id = u.user_id AND o.flag = 'fA') count FROM `user` u;
использование
LEFT JOIN
на подзапрос:SELECT u.user_id, count(o.user_id) count FROM `user` u LEFT JOIN (SELECT user_id FROM `order` WHERE flag = 'fA') o USING (user_id) GROUP BY u.user_id;
использование
LEFT JOIN
в сложном состоянии:SELECT u.user_id, count(o.user_id) count FROM `user` u LEFT JOIN `order` o ON o.user_id = u.user_id AND o.flag = 'fA' GROUP BY u.user_id;
Я думаю, самый быстрый - последний, но его нужно протестировать на достаточно больших данных и увидеть план выполнения.
Вам нужно использовать левое внешнее соединение вместо левого
SELECT
u.user_id,
COUNT(o.order_id) AS orders
FROM
`user` AS u LEFT OUTER JOIN
`order` AS o USING (user_id)
WHERE
o.flag IS NULL OR
o.flag IN ('fA')
GROUP BY
u.user_id;
Этот запрос будет работать:
SELECT
u.user_id,
COUNT(o.order_id) AS orders
FROM
`user` AS u LEFT OUTER JOIN
(SELECT user_id, order_id FROM `order` WHERE flag IS NULL OR flag IN ('fA')) as o
USING (user_id)
GROUP BY
u.user_id;
Вы можете попробовать использовать оператор CASE. Сегодня у меня нет MYSQL, поэтому я могу проверить синтаксис, но он должен быть близок к этому:
SELECT u.user_id,
CASE
WHEN (SELECT COUNT (*)
FROM ORDER z
WHERE z.user_id = USER.user_id) > 0
THEN COUNT (*)
ELSE 0
END CASE AS cnt
FROM USER
GROUP BY USER.user_id;