Количество серверов SQL из другой таблицы, если не все строки существуют - PullRequest
0 голосов
/ 04 мая 2018

Я пытаюсь получить результаты из 2 таблиц. Первая таблица - это идентификаторы с информацией, из 2-й таблицы, которую я хочу сосчитать для каждого идентификатора из 1-й таблицы, основываясь на каком-то условии. вот мой код:

SELECT p.stId, count(att.adate)
FROM payments p
LEFT JOIN Attendence att ON att.stId = p.stId
where p.cyear = 2018 and p.cmonth = 3 and p.cId = 10
and att.adate between '2018/03/01' and '2018/03/30 23:59:59.999' and att.cid 
= 10
GROUP BY p.stId

из первой таблицы (p) У меня есть 3 идентификатора. но когда я запускаю это, он возвращает только 1 идентификатор. идентификаторы, которые не существуют во 2-й таблице (т), это не дает никаких результатов. что я хочу сделать, так это то, что если во 2-й таблице нет идентификатора, я хочу вернуть 0 для счетчика (count (att.adate))

Спасибо.

Ответы [ 3 ]

0 голосов
/ 04 мая 2018

Возможно, вы пропускаете результаты, потому что в предложении where есть условия для столбцов в таблице посещаемости. Для случаев, когда нет совпадения с таблицей платежей, эти значения будут NULL. Поэтому я бы хотел, чтобы ваш запрос был таким:

SELECT p.stId, count(att.adate)
FROM payments p
LEFT JOIN Attendence att ON att.stId = p.stId
where p.cyear = 2018 and p.cmonth = 3 and p.cId = 10
and (att.adate between '2018/03/01' and '2018/03/30 23:59:59.999' OR att.adate IS NULL) and (att.cid 
= 10 or att.cid IS NULL)
GROUP BY p.stId
0 голосов
/ 04 мая 2018

Ваша проблема в том, что where превращает left join в inner join. Я также хочу упростить арифметику даты:

SELECT p.stId, count(a.adate)
FROM payments p LEFT JOIN
     Attendence a
     ON a.stId = p.stId AND a.cid = p.cid AND 
        a.adate >= '2018-03-01' AND 
        a.adate < '2018-04-01
WHERE p.cyear = 2018 and p.cmonth = 3 and p.cId = 10
GROUP BY p.stId;

Какие изменения я сделал:

  • Перемещены условия фильтрации во второй таблице в предложение ON. Так работает LEFT JOIN.
  • Я добавил условие JOIN в cid, поэтому сравнение с 10 выполняется только один раз (в предложении WHERE).
  • Изменен формат даты на ГГГГ-ММ-ДД. Это соответствует стандартным форматам даты ISO 8601.
  • Изменены BETWEEN на >= и < - я просто не хочу думать о миллисекундах при построении диапазонов дат на уровне месяца.

Отличное место, чтобы понять, почему не стоит использовать BETWEEN с датой / временем - это блог Аарона Бертранда Что общего между МЕЖДУ и Дьяволом .

0 голосов
/ 04 мая 2018

Переместите правые условия таблицы с WHERE на ON, чтобы получить истинное значение left join:

SELECT p.stId, count(att.adate)
FROM payments p
LEFT JOIN Attendence att ON att.stId = p.stId
and att.adate between '2018/03/01' and '2018/03/30 23:59:59.999' and att.cid 
= 10
where p.cyear = 2018 and p.cmonth = 3 and p.cId = 10
GROUP BY p.stId

(Когда в WHERE вы получите обычный inner join результат.)

...