使用UNION和COUNT进行DISTINCT

时间:2014-11-26 13:27:21

标签: sql sql-server

我在数据库中有一个查询,在Agenda表中返回6个结果,每天有可用的时间(例如:_08: 10: 00: 000 | 08: 30: 00: 000_)和句点(例如:T(代表afternoon}或M代表morning)。

我已经恢复了,但我有一个问题我无法解决。 我只能为每天的每个时段安排一个时间表。

示例:在2015-12-19我有一个上午的时间和下午的时间,但是在2015-12-19我早上或下午都不能有两个小时。

我的疑问是:

SELECT * FROM (
    SELECT TOP(3) agendaidentificador,agendadata, 'M' AS periodo
    FROM AGENDA
    WHERE 
        agendaconsumolocktempo IS NULL 
    AND 
        agendaconsumoidentificador IS NULL 
    AND 
        agendadata > GETDATE() 
    GROUP BY 
        agendaidentificador, 
        agendadata
    HAVING 
        CAST(DATEPART(HOUR,agendadata) AS INT) < 12 
    ORDER BY 
        NEWID(),
        agendadata asc
) A
UNION
SELECT * FROM (
    SELECT TOP(3) agendaidentificador,agendadata, 'T' AS periodo  
    FROM AGENDA
    WHERE 
        agendaconsumolocktempo IS NULL 
    AND 
        agendaconsumoidentificador IS NULL 
    AND 
        agendadata > GETDATE()
    GROUP BY 
        agendaidentificador,
        agendadata
    HAVING 
        CAST(DATEPART(HOUR,agendadata) AS INT) >= 12 
    AND 
        COUNT(CAST(agendadata AS DATE)) = 1 
    ORDER BY 
        NEWID(),
        agendadata asc
) B
GROUP BY 
    agendaidentificador, 
    agendadata,
    periodo
HAVING 
    COUNT(CAST(agendadata as DATE)) = 1
ORDER BY agendadata 

结果是:

line |agendaIdentificador |             agendaData  | periodo
-----|--------------------|-------------------------|---------
  1  |             173352 | 2015-01-12 12:50:00.000 |   T
  2  |             173363 | 2015-01-12 14:40:00.000 |   T
  3  |             175255 | 2015-01-19 11:30:00.000 |   M
  4  |             175520 | 2015-01-26 14:50:00.000 |   T
  5  |             125074 | 2015-02-25 08:20:00.000 |   M
  6  |             125076 | 2015-02-25 08:40:00.000 |   M

行不可能发生,例如行12

3 个答案:

答案 0 :(得分:2)

让我们制作一些测试数据:

DECLARE @AGENDA TABLE
(
    agendaIdentificador int,
    agendaData  datetime,
    periodo varchar(1),
    agendaconsumolocktempo int,
    agendaconsumoidentificador int

)

INSERT INTO @AGENDA
( agendaIdentificador, agendaData, periodo, agendaconsumolocktempo, agendaconsumoidentificador )
VALUES
(173352, '2015-01-12 12:50:00.000', 'T', null, null),
(173353, '2015-01-12 12:50:00.000', 'T', null, null),
(173354, '2015-01-12 12:50:00.000', 'T', null, null),
(173355, '2015-01-12 12:50:00.000', 'T', null, null),
(173356, '2015-01-13 12:50:00.000', 'T', null, null),
(173363, '2015-01-12 14:40:00.000', 'T', null, null),
(175255, '2015-01-19 11:30:00.000', 'M', null, null),
(175520, '2015-01-26 14:50:00.000', 'T', null, null),
(125074, '2015-02-25 08:20:00.000', 'M', null, null),
(125076, '2015-02-25 08:40:00.000', 'M', null, null),
(125076, '2015-02-25 08:40:00.000', 'M', null, null),
(125076, '2015-02-25 08:40:00.000', 'M', null, null),
(125076, '2015-02-25 08:40:00.000', 'M', null, null),
(125076, '2015-02-26 08:40:00.000', 'M', null, null);

现在我修复了测试数据,将早上和下午的所有记录分开并计算出来。

WITH AGENDA AS
(
    SELECT *,
    ROW_NUMBER() OVER (PARTITION BY CAST(agendaData AS DATE), periodo ORDER BY agendaData) RN
    FROM @AGENDA
)

现在我们接受之前的查询,但是下午会话的更改是我只想要每组的第一个(RN = 1)

    SELECT * FROM (
    SELECT TOP(3) agendaidentificador,agendadata, 'M' AS periodo
    FROM AGENDA
    WHERE agendaconsumolocktempo IS NULL 
    AND agendaconsumoidentificador IS NULL 
    AND agendadata > GETDATE() 
    AND DATEPART(HOUR,agendadata) < 12
    AND RN = 1
    GROUP BY 
        agendaidentificador, 
        agendadata
    ORDER BY 
        NEWID(),
        agendadata asc
) A
UNION
SELECT * FROM (
    SELECT TOP(3) agendaidentificador,agendadata, 'T' AS periodo  
    FROM AGENDA
    WHERE agendaconsumolocktempo IS NULL 
    AND agendaconsumoidentificador IS NULL 
    AND agendadata > GETDATE()
    and RN = 1
    and DATEPART(HOUR,agendadata) >= 12
    GROUP BY 
        agendaidentificador,
        agendadata
    ORDER BY 
        NEWID(),
        agendadata asc
) B
GROUP BY 
    agendaidentificador, 
    agendadata,
    periodo
ORDER BY agendadata 

这是输出:

agendaidentificador agendadata  periodo
173352  2015-01-12 12:50:00.000 T
173356  2015-01-13 12:50:00.000 T
175255  2015-01-19 11:30:00.000 M
175520  2015-01-26 14:50:00.000 T
125074  2015-02-25 08:20:00.000 M
125076  2015-02-26 08:40:00.000 M

我添加了一些更重复的记录,清理了所有无用的条款

答案 1 :(得分:0)

您必须仅按“AgendaData”的datepart分组(最后一组)。不能按整个日期+时间字段分组。

我认为这应该有效:按TO_CHAR分组(“timestamp_field”,“YYYY-MM-DD”)

答案 2 :(得分:-1)

基于@Kevin Cook回答,我刚刚添加了其他CTE,这解决了我的问题。

WITH CTE_AGENDA AS
(
    SELECT *,
    ROW_NUMBER() OVER (PARTITION BY CAST(agendaData AS DATE) ORDER BY newid(),agendaData) RN
    FROM AGENDA
)
,CTE_AGENDA2 AS
(
    SELECT *,
    ROW_NUMBER() OVER (PARTITION BY CAST(agendaData AS DATE) ORDER BY newid(),agendaData desc) RN2
    FROM AGENDA
)

SELECT * FROM (
    SELECT TOP(3) agendaidentificador,agendadata, 'M' AS periodo
    FROM AGENDA
    WHERE 
        agendaconsumolocktempo IS NULL 
    AND 
        agendaconsumoidentificador IS NULL 
    AND 
        agendadata > GETDATE() 
    GROUP BY 
        agendaidentificador, 
        agendadata
    HAVING 
        CAST(DATEPART(HOUR,agendadata) AS INT) < 12 
    ORDER BY 
        NEWID(),
        agendadata asc
) A
UNION
SELECT * FROM (
    SELECT TOP(3) agendaidentificador,agendadata, 'T' AS periodo  
    FROM AGENDA2
    WHERE     
        agendaconsumolocktempo IS NULL 
    AND 
        agendaconsumoidentificador IS NULL 
    AND 
        agendadata > GETDATE()
        and RN2 = 1
    GROUP BY 
        agendaidentificador,
        agendadata
    HAVING 
        CAST(DATEPART(HOUR,agendadata) AS INT) >= 12 
    ORDER BY 
        NEWID(),
        agendadata asc
) B
GROUP BY 
    agendaidentificador, 
    agendadata,
    periodo
HAVING 
    COUNT(CAST(agendadata as DATE)) = 1
ORDER BY agendadata,periodo