动态计算列中的值,按月分组

时间:2019-11-10 00:48:23

标签: mysql

我正在尝试获得一个mySQL查询,该查询返回按月分组的唯一值的计数。

我有一个基于类似于以下数据的表:

CREATE TABLE `animals` (
  `timestamp` datetime NOT NULL,
  `animal` tinytext NOT NULL,
  `comment` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `animals` (`timestamp`, `animal`, `comment`) VALUES
('2019-06-03 09:09:00', 'dog', 'good'),
('2019-06-03 12:00:00', 'cat', ''),
('2019-06-03 19:00:00', 'cat', ''),
('2019-07-04 09:00:00', 'cat', ''),
('2019-07-04 12:00:00', 'cat', 'feisty'),
('2019-07-04 18:51:00', 'dog', ''),
('2019-08-05 09:00:00', 'cat', ''),
('2019-08-05 12:00:00', 'cat', ''),
('2019-08-05 19:00:00', 'cat', ''),
('2019-09-06 09:00:00', 'cat', ' evil'),
('2019-09-06 12:00:00', 'cat', ''),
('2019-09-06 19:00:00', 'cat', '')

我设法编写了一个查询,该查询至少给了我每月的计数(只要它大于零),但是查询只返回了“ cat”,“ dog”或我明确指定的任何内容的计数要求。

我的目标是得到类似于以下内容的回复:

month   | dog | cat
-------------------
2019-06 | 1   | 2
2019-07 | 1   | 2
2019-08 | 0   | 3
2019-09 | 0   | 3

如何处理这样的查询?

是否可以编写一个查询来自动对动物列中的任何新值进行计数?

谢谢

3 个答案:

答案 0 :(得分:1)

您可以使用以下代码从动物栏获取灵活栏 ,为您计数。

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'Sum(`animal` =  ''',
      col,
      ''')  as `', 
      col, '`')
  ) INTO @sql
FROM
(
  select animal col
  from animals
)d;
SET @sql = CONCAT('SELECT date_format(`timestamp`, "%Y-%m") `month`, ', @sql, ' 
                  from `animals` 
                  group by `month`
                  order by `month`');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

Se dbfiddle示例https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=09d0f26087d66452fde1a22e91de7b3a

答案 1 :(得分:0)

您需要条件聚合:

select 
    date_format(`timestamp`, '%Y-%m') `month`,
    sum(`animal` = 'dog') dog,
    sum(`animal` = 'cat') cat
from `animals` 
group by `month`
order by `month`

Demo on DB Fiddle

month   | dog | cat
:------ | --: | --:
2019-06 |   1 |   2
2019-07 |   1 |   2
2019-08 |   0 |   3
2019-09 |   0 |   3

如果要动态处理列列表,则必须使用动态sql:

set @sql = null;
select 
    concat(
        'select ',
        'date_format(`timestamp`, ''%Y-%m'') `month`, ',
        group_concat(
            concat(
                'sum(`animal` = ''', 
                `animal`, 
                ''') ', 
                `animal`
            )
            order by `animal`
            separator ', '
        ),
    ' from `animals` ',
    'group by `month` '
        'order by `month`'
    )
into @sql
from (
    select distinct `animal` from `animals`
) t;

select @sql;

prepare stmt from @sql;
execute stmt;
deallocate prepare stmt;

答案 2 :(得分:0)

你可以拥有

SELECT date_format(`timestamp`, '%Y-%m') AS month, animal, COUNT(*) as count
FROM animals
GROUP BY 1, 2

但这不会为您动态提供更多列。对于更多的专栏,我想您需要构建一个动态SQL命令,循环遍历您拥有的不同动物。如果确实需要此功能,则应考虑构建为您提供SQL字符串或直接提供结果的版本。

相关问题