mysql подсчитывает строки дочерней таблицы с условием - PullRequest
3 голосов
/ 07 мая 2009

У меня есть две таблицы: «пользователь» -> «заказ»

ТАБЛИЦА: пользователь

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 появился с orders = 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 ]

4 голосов
/ 27 ноября 2013

Вы можете попробовать использовать условие в операторе '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

Пример выполнения в SQLFiddle

3 голосов
/ 07 мая 2009

Вам нужно использовать левое внешнее соединение вместо левого соединения

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;
1 голос
/ 07 февраля 2019

Есть как минимум три способа сделать это:

  1. Просто используйте зависимый подзапрос.

    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;
    
  2. Используйте 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;
    
  3. Используйте 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;
    

Самый быстрый - последний, я думаю, но его нужно протестировать на достаточно больших данных и увидеть план выполнения.

SQL Fiddle

1 голос
/ 07 мая 2009

Этот запрос будет работать:

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;
1 голос
/ 07 мая 2009

Вы можете попробовать использовать оператор 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;
...