MySQL JOIN + WHERE + GROUP BY - PullRequest
       9

MySQL JOIN + WHERE + GROUP BY

0 голосов
/ 16 января 2019

Здесь структура БД:

turns DB Table
+-----------+-------------+------------+------------+----------------+
| turnNumber| userId      | locationId | status     | itemsPurchased |
+-----------+-------------+------------+------------+----------------+
| 32        | 1           | 1          | 1          | 20             |
| 33        | 2           | 1          | 0          | 0              |
+-----------+-------------+------------+------------+----------------+

locations DB Table
+-----------+---------+---------+
| id        | Address | ZIPCode | 
+-----------+---------+---------+
| 1         | ...     | 12345   | 
| 2         | ...     | 67890   | 
+-----------+---------+---------+

Я пытаюсь получить данные о каждом местоположении (Адрес, ZIPCode ...) + количество ожидающих оборотов (со статусом 0) для каждого местоположения + сумма купленных предметовза местоположение (для всех ходов, даже если их состояние равно 1)

Здесь мой запрос:

SELECT 
    l.*, 
    COUNT(t.id) AS turns,
    SUM(IF(t.itemsPurchased > 0, t.itemsPurchased, 0)) AS items
FROM turns t RIGHT OUTER JOIN locations l
ON t.locationId = l.id          
WHERE t.status = 0 AND
l.ZIPCode = XXXX 
GROUP BY l.id

Дело в том, что когда я ставлю условие t.status, он не получает данные о местоположении, когдав таблице ходов нет хода со статусом 0, также, даже если это произойдет, я полагаю, что количество купленных предметов будет считаться только за ходы со статусом 0, а не за все ходы.

Мне интересно, есть ли способполучить все данные в одном запросе, пожалуйста, помогите!

Редактировать:

Ожидаемый результат будет следующим:

+-----------+-------------+------------+------------+----------------+
| id        | Address     | ZIPCode    | turns      | itemsPurchased |
+-----------+-------------+------------+------------+----------------+
| 1         | ...         | 12345      | 1          | 20             |
+-----------+-------------+------------+------------+----------------+

Ответы [ 2 ]

0 голосов
/ 16 января 2019

Использование левого соединения и расстановка критериев в разных местах.

Чтобы избежать этого, используя критерий в предложении WHERE для таблицы LEFT JOIN'd, он даст эффект, как если бы он был INNER JOIN.

SELECT 
loc.ZIPCode,
COUNT(DISTINCT CASE turns.status WHEN 0 THEN turns.id END) AS turns,
SUM(CASE 
    WHEN turns.status = 1 AND turns.itemsPurchased > 0 
    THEN turns.itemsPurchased 
    ELSE 0 
    END) AS items
FROM locations loc
LEFT JOIN turns ON turns.locationId = loc.id
WHERE loc.ZIPCode = 12345
GROUP BY loc.id, loc.ZIPCode
0 голосов
/ 16 января 2019

Условие "t.status = 0" в предложении WHERE отрицает "внешность" соединения;тот же результат, который мы получили бы с INNER JOIN.

При внешнем соединении все строки в locations, у которых нет совпадающей строки в turns, будут возвращены со значениями NULL для всехиз t. столбцов.Несоответствующие строки из locations будут исключены условием в предложении WHERE.


Рассмотрите возможность перемещения этого условия из предложения WHERE в предложение ON внешнего соединения.

Или рассмотрите возможность перемещения этого условия в агрегированное выражение.

Как пример:

SELECT l.id
     , l.zipcode
     , SUM(IF(t.status = 0, 1, 0)) AS turns
     , SUM(IF(t.status = 0 AND t.itemspurchased > 0, t.itemspurchased, 0)) AS items
 FROM locations l

 LEFT 
 JOIN turns t
   ON t.locationid = l.id
  AND t.status     = 0 

WHERE l.zipcode = XXXX 
GROUP
   BY l.id
    , l.zipcode
...