1.48表格如下所示:

CREATE TABLE `history` (
    `TIMESTAMP` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    `DEVICE` VARCHAR(64) NULL DEFAULT NULL COLLATE 'utf8_bin',
    `TYPE` VARCHAR(64) NULL DEFAULT NULL COLLATE 'utf8_bin',
    `EVENT` VARCHAR(512) NULL DEFAULT NULL COLLATE 'utf8_bin',
    `READING` VARCHAR(64) NULL DEFAULT NULL COLLATE 'utf8_bin',
    `VALUE` VARCHAR(128) NULL DEFAULT NULL COLLATE 'utf8_bin',
    `UNIT` VARCHAR(32) NULL DEFAULT NULL COLLATE 'utf8_bin'
)
COLLATE='utf8_bin'
ENGINE=InnoDB
;

和一些看起来像这样的数据(只是可用数据的一个小示例)

INSERT INTO `history` (`TIMESTAMP`, `DEVICE`, `TYPE`, `EVENT`, `READING`, `VALUE`, `UNIT`) VALUES ('2023-01-04 21:16:06', 'DL_Motion', 'CUL_HM', 'state: motion', 'state', 'motion', '');
INSERT INTO `history` (`TIMESTAMP`, `DEVICE`, `TYPE`, `EVENT`, `READING`, `VALUE`, `UNIT`) VALUES ('2023-01-04 22:31:09', 'CD_Motion', 'CUL_HM', 'state: motion', 'state', 'motion', '');
INSERT INTO `history` (`TIMESTAMP`, `DEVICE`, `TYPE`, `EVENT`, `READING`, `VALUE`, `UNIT`) VALUES ('2023-01-04 23:24:58', 'AB_Motion', 'CUL_HM', 'state: motion', 'state', 'motion', '');
INSERT INTO `history` (`TIMESTAMP`, `DEVICE`, `TYPE`, `EVENT`, `READING`, `VALUE`, `UNIT`) VALUES ('2023-01-05 00:25:58', 'XY_Motion', 'CUL_HM', 'state: motion', 'state', 'motion', '');
INSERT INTO `history` (`TIMESTAMP`, `DEVICE`, `TYPE`, `EVENT`, `READING`, `VALUE`, `UNIT`) VALUES ('2023-01-05 01:27:58', 'XY_Motion', 'CUL_HM', 'state: motion', 'state', 'motion', '');
INSERT INTO `history` (`TIMESTAMP`, `DEVICE`, `TYPE`, `EVENT`, `READING`, `VALUE`, `UNIT`) VALUES ('2023-01-05 02:27:58', 'DL_Motion', 'CUL_HM', 'state: motion', 'state', 'motion', '');
INSERT INTO `history` (`TIMESTAMP`, `DEVICE`, `TYPE`, `EVENT`, `READING`, `VALUE`, `UNIT`) VALUES ('2023-01-05 02:29:02', 'DL_Motion', 'CUL_HM', 'state: motion', 'state', 'motion', '');

我想要将事件的数量按日期和时间分组,用于专用设备,其工作方式如下:

SELECT 
  DATE_FORMAT(TIMESTAMP,"%Y-%m-%d %H") AS ftimestamp,
  COUNT(TIMESTAMP) AS amount
FROM 
    history
WHERE  
  DEVICE = 'DL_Motion' 
  AND READING = 'state'
  AND VALUE = 'motion'
GROUP BY 
    YEAR(TIMESTAMP),MONTH(TIMESTAMP),DAY(TIMESTAMP),HOUR(TIMESTAMP); 

得出的结论是:

ftimestamp amount
2023-01-04 21 1
2023-01-05 02 2

为了可视化的目的,如果我能得到这样的结果就太好了:

ftimestamp amount
2023-01-04 21 1
2023-01-04 22 0
2023-01-04 23 0
2023-01-04 00 0
2023-01-04 01 0
2023-01-05 02 2

So all possible dates and hours where no data available shall have a zero.
There are enough data in the table to generate the list of all possible dates and hours with the following select:

SELECT
    DATE_FORMAT(TIMESTAMP,"%Y-%m-%d %H") AS ftimestamp
FROM
    history
GROUP BY
    YEAR(TIMESTAMP),MONTH(TIMESTAMP),DAY(TIMESTAMP),HOUR(TIMESTAMP);

我不知道如何将这两个要求结合起来才能得到我想要的结果.

推荐答案

如果表中有所有可用日期,则可以使用条件聚合:

select date_format(timestamp, '%Y-%m-%d %H') as timestamp_hr,
    sum(device = 'DL_Motion' and reading = 'state' and value = 'motion') as amount
from history
group by date_format(timestamp, '%Y-%m-%d %H')

逻辑是扫描整个表,以便我们确实获得所有可用日期,然后使用条件sum()仅计算相关行.

注意,我在selectgroup by子句中对齐了日期表达式,这在标准SQL中更有意义.

Sql相关问答推荐

为什么在这种情况下我不能使用LAG函数?

当交叉联接3个或更多表时,实体框架中是否会传输冗余的行数据并占用数据库带宽?

删除事务中的本地临时表

用于过滤嵌套对象或数组中的JSON数据的WHERE条件

SQL到Snowflake-转换嵌套的SELECT(值

无法访问级联删除导致的触发器中已删除的外键记录

更改重复值的情况

删除行而不使数据库超载

计算不同模式的时间跨度

仅当 SQL Server 中的表为开时,才在存储过程中使用更改跟踪

更新之前如何获得价值

批量更改WooCommerce中所有产品的税收状态

根据潜在空值的条件对记录进行计数

将 MERGE 语句与 Oracle PL/SQL 表类型一起使用时,导致无效数据类型错误的原因是什么?

使用 regexp_replace 替换所有出现的特殊字符

SQL Server 分区和 Run Case 语句

如何在 PL/SQL 中区分返回的 XML 值?

奇怪的甲骨文行为

在sql server中创建唯一标识符列

Lag() 获取snowflake的值变化