Как использовать COUNT с GROUP BY на двух полях - PullRequest
0 голосов
/ 31 мая 2019

Я пытаюсь написать запрос, в котором все здания будут отображаться для каждой даты, а нули перечислены для тех, которые не существуют.Ниже приведены пример таблицы и данные для моего примера.

CREATE TABLE IF NOT EXISTS `table1` (
  `id` int(6) unsigned NOT NULL,
  `buildings` char(3) NOT NULL,
  `date` varchar(50) NOT NULL,
  `sold` char(1) NOT NULL,
  PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
INSERT INTO `table1` (`id`, `buildings`, `date`, `sold`) VALUES
  ('1', '1', '2019-04-22 07:40:08','X'),
  ('2', '1', '2019-04-22 07:41:15',''),
  ('3', '1', '2019-04-22 07:42:10','X'),
  ('4', '3', '2019-04-22 07:43:50','X'),
  ('5', '1', '2019-04-22 07:44:27',''),
  ('6', '2', '2019-05-21 06:43:17','X'),
  ('7', '2', '2019-05-21 07:36:17',''),
  ('8', '1', '2019-05-21 06:32:22','X'),
  ('9', '3', '2019-05-21 07:43:50',''),
  ('10', '2', '2019-05-21 07:44:27','X');

И SQL-запрос, который я использую на данный момент, приведен ниже.CONCAT и MID, используемые для построения первого столбца, получают год и неделю года для создания 4-значного кода в неделю.

SELECT CONCAT(MID(date,3,2),
           LPAD(WEEK(CONCAT(MID(date,1,4),'-',
           MID(date,6,2),'-',
           MID(date,10,2))),2,0)) AS YearWeek, 
       buildings, 
       COUNT(sold) AS count 
FROM table1 
WHERE sold = 'X' 
GROUP BY CONCAT(MID(date,3,2),
           LPAD(WEEK(CONCAT(MID(date,1,4),'-',
           MID(date,6,2),'-',
           MID(date,10,2))),2,0)),
         buildings

Моя проблема заключается в том, что я получаю данные, как показано ниже

YearWeek    buildings   count
1913        1           2
1913        3           1
1917        1           1
1917        2           2

Когда на самом деле мне бы хотелось, чтобы данные выглядели так, как показано ниже, я мог бы их отобразить.

YearWeek    buildings   count
1913        1           2
1913        2           0
1913        3           1
1917        1           1
1917        2           2
1917        3           0

Чтобы добиться этого, я попытался выполнить левое соединение сподзапрос (выберите отдельное здание как здания из таблицы 1), но это не работает, и я думаю, что это связано с тем, что я группируюсь по YearWeek, а затем строю, а не наоборот. '

Любая помощьпо этому запросу будет высоко ценится!

1 Ответ

3 голосов
/ 31 мая 2019

Вы можете получить желаемые результаты, взяв CROSS JOIN различных значений YearWeek и buildings, чтобы получить все возможные комбинации каждого из них, а затем используя LEFT JOIN для таблицы, чтобы получить счеткаждого типа buildings продано на этой неделе.Например:

SELECT yw.YearWeek,
       b.buildings,
       COALESCE(SUM(t.sold = 'X'), 0) AS count
FROM (SELECT DISTINCT buildings
      FROM table1) b
CROSS JOIN (SELECT DISTINCT RIGHT(YEARWEEK(date),4) AS YearWeek
            FROM table1) yw
LEFT JOIN table1 t ON t.buildings = b.buildings AND RIGHT(YEARWEEK(t.date),4) = yw.YearWeek
GROUP BY yw.YearWeek, b.buildings

Вывод:

YearWeek    buildings   count
1916        1           2
1916        2           0
1916        3           1
1920        1           1
1920        2           2
1920        3           0

Демонстрация на dbfiddle

Примечание. Я использовал встроенный MySQL YEARWEEK Функция для упрощения запроса, вы можете просто подставить формулу, если она не подходит.

...