如何在两个字段上将COUNT与GROUP BY一起使用

时间:2019-05-30 22:53:26

标签: mysql sql join group-by left-join

我正在尝试编写一个查询,其中每个日期都会显示所有建筑物,而对于不存在的建筑物则列出零。下面是示例表和示例数据。

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 个答案:

答案 0 :(得分:3)

通过获取不同的CROSS JOINYearWeek值中的buildings来获取每个值的所有可能组合,然后使用{{1} }到表格中,以获取该周售出的每种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

Demo on dbfiddle

请注意,我已经使用了MySQL的内置YEARWEEK函数来简化查询,如果不合适,您可以简单地替换公式。