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

时间:2011-08-25 21:11:38

标签: sql postgresql case

假设我有一个类似

的表格
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

我想要一个SQL语句,将当天分为3个班次(22:00:00.001到06:00:00:00,06:00:00.001到14:00:00:00,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:00000之间工作再次从同一天的22:00:00.001到00:00:00000,而不是从前一天的00:00:00:00到当天的06:00:00:00
  2. 日期只是比较小时,这样,从22:00:00到00:22:59:59.999的每条记录都计入第2班,而不是第3班,这是正确的。
  3. 任何艰难的事情?

    提前感谢。

1 个答案:

答案 0 :(得分:0)

我认为以下是你想要的......

首先,如果您还没有Calendar File,那么您将需要{{3}}。

其次,继续并定义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的实例。