了解GroupBY

时间:2017-07-04 14:53:30

标签: sql-server tsql group-by

我在SQL Server中有一个表,其中记录了个人输入和输出。 同一天有多个小时的进入或退出。我需要的是恢复当天的第一个入口和最后一个出口。

Date       hour   Clock
------------------------
01/01/2017 09:00  1
01/01/2017 11:30  2
01/01/2017 17:00  2
02/01/2017  7:59  1
02/01/2017 16:00  1

我有这个SQL查询可以正常工作。

SELECT  
    d.Date,
    MIN(d.hour) as Entry, 
    MAX(dt.hour) as Exit   
FROM 
    #temp1 AS d
LEFT JOIN 
    #temp1 AS dt ON d.Date = dt.Date
GROUP BY 
    d.Date
ORDER BY
    Date DESC

但如果我在查询中再添加2列

SELECT  
    d.Date,
    d.clock as ClockEntry,       -- Aggregated column to display
    MIN(d.hour) as Entry, 
    dt.clock as ClockExit,       -- Aggregated column to display
    MAX(dt.hour) as Exit
FROM 
    #temp1 AS d
LEFT JOIN 
    #temp1 AS dt ON d.Date = dt.Date
GROUP BY   
    d.Date
ORDER BY
    Date DESC

我收到此错误:

  

专栏'#temp1.clock'在选择列表中无效,因为它不包含在聚合函数或GROUP BY子句中。

我只需按字段分组"日期",我不想为GROUP BY添加更多条件..我怎么能解决它?

我想要这个结果

DATE        ClockEntry     Entry    ClockExit    Exit     
-------------------------------------------------------
01/01/2017     1           09:00        2        17:00
02/01/2017     1            7:59        1        16:00

2 个答案:

答案 0 :(得分:1)

所以有一种简单的方法可以做到这一点 - 使用2个排名功能:

  1. 按日期分区,按小时升序排序
  2. 按日期分区,按小时降序排序
  3. 此时,可以将行连接在一起,它们的值均为1,并且日期匹配。

    我倾向于使用CTE:

    with temp2 (MinId, MaxId, Date, Hour, Clock)
    AS
    (
        select ROW_NUMBER() Over (partition by date order by hour), 
         ROW_NUMBER() Over (partition by date order by hour desc), 
        *
        from temp1
    )
    select distinct 
           d1.Date,
           d1.Clock,
           d1.Hour,
           d2.Clock,
           d2.Hour
    FROM temp2 d1
    LEFT JOIN temp2 d2 
        ON d1.Date = d2.Date  -- dates match
        AND d1.MinId=d2.MaxId -- minId=earliest record MaxId=latest record
    WHERE d1.MinId=1
    

答案 1 :(得分:-1)

GROUP BY方法

如果您知道只有一个值会出现clock列, 只需使用MAXMIN聚合函数汇总值,例如:

SELECT  
d.Date,
MIN(d.clock) as ClockEntry,
MIN(d.hour) as Entry, 
MAX(dt.clock) as ClockExit,
MAX(dt.hour) as Exit

FROM #temp1 AS d
LEFT JOIN #temp1 AS dt 
ON d.Date= dt.Date
GROUP BY   d.Date
order by Date desc

或者,如果您有多个时钟值并希望全部看到它们, 将它们添加到GROUP BY语句中:

SELECT  
d.Date,
d.clock as ClockEntry,
MIN(d.hour) as Entry, 
dt.clock as ClockExit,
MAX(dt.hour) as Exit

FROM #temp1 AS d
LEFT JOIN #temp1 AS dt 
ON d.Date= dt.Date
GROUP BY   d.Date, d.clock, dt.clock
order by Date desc

ORDER BY方法

每个日期使用cursorCommon Table Expression来获得第一个条目和最后一个条目。

指定日期的首次参赛

SELECT TOP 1 d.date, d.clock as ClockEntry, d.hour as Entry
FROM #temp1 AS d
WHERE d.date = @myDate
ORDER BY d.hour ASC

指定日期的最后一次退出

SELECT TOP 1 d.date, d.clock as ClockExit, d.hour as Exit
FROM #temp1 AS d
WHERE d.date = @myDate
ORDER BY d.hour DESC

参考:

GROUP BY Documentation
AGGREGATE FUNCTIONS