sql - 在一天中的时间段内计算结果

标签 sql postgresql case

假设我有一张 table

CREATE TABLE associacao
(
  id bigserial NOT NULL,
  idusuario character varying(50),
  idunit character varying(50),
  dataassociacao timestamp with time zone,
  codigo bigint NOT NULL DEFAULT 0,
  CONSTRAINT associacao_pkey PRIMARY KEY (id)
)

数据如

id | idusuario | idunit | dataassociacao               | codigo
1  | "100000"  | "200"  | "2011-08-25 10:20:25.123-03" |   3
2  | "100000"  | "300"  | "2011-08-25 10:20:25.123-03" |   3
3  | "400000"  | "500"  | "2011-08-25 05:20:26.123-03" |   3
4  | "400000"  | "600"  | "2011-08-25 05:20:26.123-03" |   3
5  | "700000"  | "800"  | "2011-08-25 16:20:26.123-03" |   3
6  | "700000"  | "900"  | "2011-08-25 16:20:26.123-03" |   3
7  | "1000000" | "1100" | "2011-08-25 21:20:26.123-03" |   3
8  | "1200000" | "1300" | "2011-08-24 22:20:23.123-03" |   2
9  | "1200000" | "1300" | "2011-08-24 22:20:26.123-03" |   3

我想要一个将一天分为 3 个类次的 SQL 语句(22:00:00.001 到 06:00:00.000、06:00:00.001 到 14:00:00.000 和 14:00:00.001 到 22:00: 00.000) 并计算每个部分有多少个不同的 idusuario。

到目前为止,我得到了以下代码:

SELECT 
    CASE  
       WHEN DATE_PART('hour', dataassociacao) BETWEEN 6 AND 14 THEN 1 
       WHEN DATE_PART('hour', dataassociacao) BETWEEN 14 AND 22 THEN 2 
       WHEN DATE_PART('hour', dataassociacao) BETWEEN 22 AND 24 THEN 3 
       WHEN DATE_PART('hour', dataassociacao) BETWEEN 0 AND 6 THEN 3
    END AS data, COUNT(distinct idusuario)
FROM associacao
WHERE codigo = 3
GROUP BY data
ORDER BY data;

这给了我下表(上面的例子)

data | count(idusuario)
 1   |       1
 2   |       3
 3   |       1

我的问题是:

  1. 如果我想按天计算,我不会正确计算类次,例如,第 3 类(夜类)将被计算为好像他们从 00:00:00.001 到 06:00:00.000 工作,然后再次从 22:00:00.001 到同一天的 00:00:00.000,而不是从前一天的 22:00:00.001 到当天的 06:00:00.000
  2. 日期只比较小时,这样,从 22:00:00.000 到 22:59:59.999 的每条记录都计入第二类,而不是第三类,这是正确的。

有什么问题吗??

提前致谢。

最佳答案

我认为以下内容符合您的要求...

首先,您需要一个 Calendar File ,如果您还没有的话。

其次,继续定义一个 Shift 表。这在任何情况下都可能对跟踪很重要,并且在这里至关重要。快速而肮脏的定义:

CREATE TABLE Shift (Shift INTEGER NOT NULL, 
                    Start_Offset SMALLINT NOT NULL,
                    End_Offset SMALLINT NOT NULL,
                    CONSTRAINT Shift_PK PRIMARY KEY(Shift))

要插入的数据:

INSERT INTO Shift VALUES(1, 6, 14), (2, 14, 22), (3, 22, 30)

然后您应该能够运行此查询:

SELECT a.Calendar_Date, b.Shift, COUNT(DISTINCT c.idusuario)
FROM calendar as a
CROSS JOIN Shift as b
JOIN associacao as c
ON c.dataassociacao >= a.Calendar_Date + ((INTERVAL '1 hours') * b.Start_Offset)
AND c.dataassociacao < a.Calendar_Date + ((INTERVAL '1 hours') * b.End_Offset)
GROUP BY a.Calendar_Date, b.Shift
ORDER BY a.Calendar_Date, b.Shift

这导致:

Calendar_Date    Shift    Count
=======================================
2011-08-24       3        2
2011-08-25       1        1
2011-08-25       2        2 

(请注意:我在 DB2 上执行了所有构建/测试工作,它没有间隔函数。从在线查看文档和相关信息来看,给定的查询应该等同于我写了什么,但我无法在 PostgreSQL 实例上进行测试)。

关于sql - 在一天中的时间段内计算结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7197237/

相关文章:

SQL Server : use function to calculate a new column

sql - 创建查询以在 "join"表中查找匹配对象

php - MySQL:使用 CASE/ELSE 值作为连接参数

sql-server - CASE 语句中随机生成的值返回 NULL

php - MySQL 哪里有很多多对多的匹配项?

Sql 在两个表之间加入一个组

mysql - INNER JOIN 导致重复行

postgresql - 带有插入但没有复制操作的postgres转储

postgresql - Liquibase:添加外键约束时指定架构

list - 为什么 `Nil` 被定义为 `case object`