【问题标题】:How I can group the results by day in this query with SQL Server?如何使用 SQL Server 在此查询中按天对结果进行分组?
【发布时间】:2016-08-11 08:35:48
【问题描述】:

sql fiddle demo here

我有这个日记表的表结构:

 CREATE TABLE Diary
(
     [IdDiary] bigint, 
     [UserId] int,
     [IdDay] numeric(18,0),
     [IsAnExtraHour] bit
);

INSERT INTO Diary ([IdDiary],  [UserId],  [IdDay], [IsAnExtraHour])
values 
(51, 1409, 1, 0),
(52, 1409, 1, 1),
(53, 1409, 3, 0),
(54, 1409, 5, 0),
(55, 1409, 5, 1),
(56, 1408, 2, 0);

DiaryTimetable 表的结构如下:

CREATE TABLE DiaryTimetable
(
     [IdDiary] bigint, 
     [Hour] varchar(50)
);

  INSERT INTO DiaryTimetable ([IdDiary], [Hour])
VALUES
    (51, '09:00'),
    (51, '09:30'),
    (51, '10:00'),
    (51, '10:30'),
    (51, '11:00'),
    (52, '15:00'),
    (52, '15:30'),
    (52, '16:00'),
    (52, '16:30'),
    (52, '17:00'),
    (53, '11:00'),
    (53, '11:30'),
    (53, '12:00'),
    (53, '12:30'),
    (53, '13:00'),
    (54, '10:00'),
    (54, '10:30'),
    (54, '11:00'),
    (54, '11:30'),
    (54, '12:00'),
    (55, '16:00'),
    (55, '16:30'),
    (55, '17:00'),
    (55, '17:30'),
    (55, '18:00'),
    (56, '15:00'),
    (56, '15:30'),
    (56, '16:00'),
    (56, '16:30'),
    (56, '17:00');

我使用此查询来获取用户 ID 1409 的最大小时和最小小时,以获取每天输入的时间和离开工作的时间。 idday 对应于星期几。例如 1 是星期一,2 是星期二等等...

 SELECT d.IdDiary, d.IdDay, MIN(Hour) as 'Start Time', MAX(Hour) as 'End Time', IsAnExtraHour
FROM Diary AS d
LEFT JOIN DiaryTimetable AS dt ON d.IdDiary = dt.IdDiary
where userid = 1409
GROUP BY d.IdDiary, d.IdDay, IsAnExtraHour

这个查询给出这个结果:

我想得到这个结果:

    Day       Start Time    End Time    Start Extra Time    End Extra Time
    -----     ----------    --------    ---------------     ---------------
   Monday       09:00         11:00        15:00                17:00
   Wednessday   11:00         13:00        
   Friday       10:00         12:00        16:00                18:00

我有一个列 (IsAnExtraHour) 此列指示该行是否在一天中有额外的时间,例如一个员工在星期一 09:00 到 11:00 开始工作,然后在下午 15:00 再次工作到17:00,所以我想知道如何将这个时间分组在同一行,希望我已经能够表达清楚,我接受建议谢谢。

【问题讨论】:

  • 应该这样问 SQL 问题。一切都像 Esraa_92 一样!
  • 感谢您的评论;-D
  • 不要对列别名使用单引号。为避免混淆和难以发现的错误,您应该只对字符串和日期/时间常量使用单引号。

标签: sql sql-server time group-by inner-join


【解决方案1】:
SELECT  d.IdDay,
        MIN(CASE WHEN isAnExtraHour = 0 THEN hour END) as 'Start Time',
        MAX(CASE WHEN isAnExtraHour = 0 THEN hour END) as 'End Time',
        MIN(CASE WHEN isAnExtraHour = 1 THEN hour END) as 'Start Extra Time',
        MAX(CASE WHEN isAnExtraHour = 1 THEN hour END) as 'End Extra Time'
FROM    Diary AS d
LEFT JOIN
        DiaryTimetable AS dt
ON      dt.IdDiary = d.IdDiary
WHERE   userid = 1409
GROUP BY
        d.IdDay

【讨论】:

  • 感谢您的回答,这很容易理解:-D
【解决方案2】:

我使用来自@Quassnoi 的代码并添加了这个:

SELECT DATENAME(weekday, d.idday-1) as 'Day' ,
       MIN(CASE WHEN isAnExtraHour = 0 THEN hour END) AS 'Start Time',
       MAX(CASE WHEN isAnExtraHour = 0 THEN hour END) AS 'End Time',
       MIN(CASE WHEN isAnExtraHour = 1 THEN hour END) AS 'Start Extra Time',
       MAX(CASE WHEN isAnExtraHour = 1 THEN hour END) AS 'End Extra Time'
FROM Diary AS d
LEFT JOIN DiaryTimetable AS dt ON dt.IdDiary = d.IdDiary
WHERE userid = 1409
GROUP BY d.IdDay

我希望这对某人有所帮助,谢谢大家的回答。

【讨论】:

    【解决方案3】:

    我解决这个问题的方法是分别计算你的标准时间和加班时间,就像这样;

    SELECT d.IdDay
        ,MIN(dt.StartTime) AS 'Start Time'
        ,MAX(dt.EndTime) AS 'End Time'
        ,MIN(ex.StartTime) AS 'Start Extra Time'
        ,MAX(ex.EndTime) AS 'End Extra Time'
    FROM Diary AS d
    LEFT JOIN (
        SELECT IdDiary
            ,MIN(Hour) AS StartTime
            ,MAX(Hour) AS EndTime
        FROM DiaryTimetable
        GROUP BY IdDiary
        ) AS dt ON d.IdDiary = dt.IdDiary
        AND d.IsAnExtraHour = 0
    LEFT JOIN (
        SELECT IdDiary
            ,MIN(Hour) AS StartTime
            ,MAX(Hour) AS EndTime
        FROM DiaryTimetable
        GROUP BY IdDiary
        ) AS ex ON d.IdDiary = ex.IdDiary
        AND d.IsAnExtraHour = 1
    WHERE userid = 1409
    GROUP BY d.IdDay
    

    【讨论】:

    • 当然,您可以在 IdDay 上做一个 case 语句,或者如果您有一个将日期作为文本返回的日期表(例如星期一而不是 1),则可以将其链接到日期表
    【解决方案4】:

    您可以先获得非加班时间,然后通过 UserId 和 IdDay 将加班时间留给他们。像这样:

    SELECT
        CASE BaseHours.IdDay
            WHEN 1 THEN 'Monday' 
            WHEN 2 THEN 'Tuesday' 
            WHEN 3 THEN 'Wednesday' 
            WHEN 4 THEN 'Thursday' 
            WHEN 5 THEN 'Friday' 
            WHEN 6 THEN 'Saturday' 
            WHEN 7 THEN 'Sunday' 
        END AS [WeekDay],
        MIN(BaseTimeTable.Hour) as 'Start Time',
        MAX(BaseTimeTable.Hour) as 'End Time',
        MIN(ExtraTimeTable.Hour) as 'Start Extra Time',
        MAX(ExtraTimeTable.Hour) as 'End Extra Time'
    FROM Diary AS BaseHours
    LEFT JOIN Diary ExtraHours
        ON ExtraHours.UserId = BaseHours.UserId
            AND ExtraHours.IdDay = BaseHours.IdDay AND ExtraHours.IsAnExtraHour = 1
    JOIN DiaryTimetable AS BaseTimeTable
        ON BaseHours.IdDiary = BaseTimeTable.IdDiary
    LEFT JOIN DiaryTimetable AS ExtraTimeTable
        ON ExtraHours.IdDiary = ExtraTimeTable.IdDiary
    WHERE BaseHours.Userid = 1409 AND BaseHours.IsAnExtraHour = 0
    GROUP BY BaseHours.IdDay
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-23
      • 2014-01-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-03
      相关资源
      最近更新 更多