SQL Pivot(?) - Flatten By-Day / Event选择包含一整周的列

时间:2018-06-07 23:11:32

标签: sql-server

我希望有人能够帮助我弄清楚如何使用所显示的表来展平选择,这样我就可以为每个User选择一行,其中包含每个事件的列。

简而言之,我正在创建以下临时表,并且它充满了特定用户在特定周内参加的事件。

CREATE TABLE #ByEvent
       (WeekBegin        SMALLDATETIME      NOT NULL,
        UserNo           INT                NOT NULL,
        Name             VARCHAR(30)        NOT NULL,
        Attend           BIT                NOT NULL,               
        --- Event Portion ---------------------------   
        EventID          INT                NOT NULL,
        EventDate        SMALLDATETIME      NOT NULL,
        Hrs              NUMERIC(4,2)       NOT NULL,
        EventScheduleBeg SMALLDATETIME      NOT NULL,
        EventScheduleEnd SMALLDATETIME      NOT NULL,               
        Val1             VARCHAR(1)         NOT NULL,
        Val2             VARCHAR(1)         NOT NULL)   

请参阅下面的示例表内容。为清晰起见,我已将一些值减少到相关部分:

WeekBegin   UserNo  Name   Attend EventID EventDate  Hrs  ScheduleBeg  ScheduleEnd
2018-05-27  24      Jim    T      257     5/29/18    4.0  12:00        16:00  
2018-05-27  24      Jim    T      258     5/29/18    2.0  18:00        20:00
2018-05-27  24      Jim    T      259     5/30/18    2.5  12:00        14:30   
2018-05-27  24      Tim    F      259     5/30/18    2.5  12:00        14:30   

我需要的是输出数据,如下面的选择所示。但是,我无法理解如何实现这一目标。我相信我需要一个支点(如果我在错误的轨道上并且过度复杂,请告诉我),但在给定的一周内可能没有或有5个以上的事件,因此我不知道如何我在select语句中需要的许多列。希望这是有道理的。如果有人指出我正确的方向,我真的很感激!

SELECT WeekBegin
      ,UserNo
      ,Name
      ,Attend
      ,FirstEventID
      ,FirstEventDate
      ,FirstEventHrs
      ,FirstEventScheduleBeg
      ,FirstEventScheduleEnd
      ,FirstVal1
      ,FirstVal2
      ,SecondEventID
      ,SecondEventDate
      ,SecondEventHrs
      ....

1 个答案:

答案 0 :(得分:1)

这会让你开始,但你真的应该在这个问题上添加更多细节。例如,似乎没有对事件数量的硬限制,并且您可能希望只有必要的列数。动态SQL解决方案能够实现这一点,但是如果你确实需要以"第一","第二","第三"为前缀的列。等等,你有另一个小障碍要克服这个要求。

顺便说一下,有很多方法可以按周分组,并且在5月份对随机日期进行硬编码可能不是您在生产代码中实际使用的方法。

;with data as (
    select *,
        datediff(week, cast('20180527' as date)) as WeekNo,
        row_number() over (
            partition by UserNo order by EventDate, ScheduleBeg) as RN
    from #ByEvent
    where EventDate >= cast('20180527' as date)
)
select WeekNo, UserNo, ...
    case when RN = 1 then EventID end as FirstEventID, ...
    case when RN = 2 then EventID end as SecondEventID, ...
from data
group by WeekNo, UserNo;