根据组顺序选择新列

时间:2015-05-25 07:14:36

标签: sql sql-server group-by sql-order-by

我在这个网站上经历过很多问题,但是无法找到解决方案。 我有一张桌子:

Date    GroupID CHANNEL
24/02/2015  1   A
26/02/2015  1   B
27/02/2015  1   C
21/03/2015  2   D
20/02/2015  3   E
25/02/2015  3   D
28/02/2015  4   C
04/03/2015  5   B
05/03/2015  5   E
10/03/2015  5   D
11/03/2015  5   A
14/03/2015  5   C
23/03/2015  5   F
28/03/2015  6   E

频道仅限于'A','B','C','D','E','F'。它中有很多行有不同的GROUPID。

我需要得到这张桌子:

Date    GroupID Channel isFirst isLast  Channelsingroup Daysbeforelast
24/02/2015  1       A   TRUE    FALSE   3                   3
26/02/2015  1       B   FALSE   FALSE   3                   1
27/02/2015  1       C   FALSE   TRUE    3                   0
21/03/2015  2       D   TRUE    TRUE    1                   0
20/02/2015  3       E   TRUE    FALSE   2                   5
25/02/2015  3       D   FALSE   FALSE   2                   0
28/02/2015  4       C   TRUE    TRUE    1                   0
04/03/2015  5       B   TRUE    FALSE   6                   19
05/03/2015  5       E   FALSE   FALSE   6                   18
10/03/2015  5       D   FALSE   FALSE   6                   13
11/03/2015  5       A   FALSE   FALSE   6                   12
14/03/2015  5       C   FALSE   FALSE   6                   9
23/03/2015  5       F   FALSE   FALSE   6                   0
28/03/2015  6       E   TRUE    TRUE    1                   0

<li> </li><li> </li>当Channel是具有按时间排序的相同ID的行组中的第一个时;否则为假。

.container li{ list-style-type: none; float:left; padding: 5px 12px; display: inline-block; position: relative; width: 20% } 当Channel是具有按时间排序的相同GroupID的行组中的最后一个;否则为假。

IsFirst = TRUE - 同一组中的行数(具有相同的GroupID)

IsLast = TRUE - 在该组的最新一行与当前行之间的天数中的约会。

我无权创建或更新表,只能选择。

我希望以上数据有意义,有任何问题请告诉我。

4 个答案:

答案 0 :(得分:4)

一种解决方案可能是使用窗口聚合函数:

select 
    *, 
    case when date = MIN(date) over (partition by groupid order by groupid) then 'TRUE' else 'FALSE' end isFirst,
    case when date = MAX(date) over (partition by groupid order by groupid) then 'TRUE' else 'FALSE' end isLast,
    count(*) over (partition by groupid order by groupid) Channelsingroup,
    datediff(day,date,MAX(date) over (partition by groupid order by groupid)) Daysbeforelast
from your_table

Sample SQL Fiddle

答案 1 :(得分:3)

您可以使用ROW_NUMBER获取isFirstisLast列以及COUNT(*) OVER()的{​​{1}}。此外,您可以使用ChannelsInGroup来计算CROSS APPLY

SQL Fiddle

DaysBeforeLast

<强>结果

WITH Cte AS(
    SELECT *,
        RN = ROW_NUMBER() OVER(PARTITION BY GroupID ORDER BY [Date]),
        CC = COUNT(*) OVER(PARTITION BY GroupID)
    FROM TestData
)
SELECT
    c.[Date],
    c.GroupID,
    c.Channel,
    isFirst         = CASE WHEN c.RN = 1 THEN 'TRUE' ELSE 'FALSE' END,
    isLast          = CASE WHEN c.RN = c.CC THEN 'TRUE' ELSE 'FALSE' END,
    ChannelsInGroup = c.CC,
    DaysBeforeLast  = DATEDIFF(DAY, c.[Date], x.LastDate)
FROM Cte c
CROSS APPLY(
    SELECT TOP 1 [Date]
    FROM Cte
    WHERE 
        RN = CC
        AND GroupID = c.GroupID
    ORDER BY [Date] DESC
)x(LastDate)

答案 2 :(得分:0)

试试这个。

select   DATE_1 ,GroupID,CHANNEL
         , case (select top 1 test.CHANNEL 
                 from test 
                 where test.GroupID = outer1.GroupID
                    order by test.CHANNEL) when outer1.CHANNEL then 'true' else 'false' end as isFirst 
        , case (select top 1 test.CHANNEL 
                 from test 
                 where test.GroupID = outer1.GroupID 
                    order by test.CHANNEL desc) when CHANNEL then 'true' else 'false' end as isLast
        , (select count(*)
           from test 
             where test.GroupID = outer1.GroupID) Channelsingroup 
        , (select DATEDIFF(DAY,outer1.DATE_1,MAX(test.DATE_1))
           from test 
           where test.GroupID = outer1.GroupID)

from     test outer1

答案 3 :(得分:0)

 with cte 
 as 
 (select Date,GroupID ,Channel,row_number() over (partition by groupid order         

 by groupid) as first
 from table1)
 select Date,GroupID, Channel, case when first=1 then 'true' else 'false' end as 
 isFirst,
 case when isfirst=b.Channelsingroup then 'true' else 'false' end as isLast
 b.Channelsingroup, datediff(dd,getdate(),Daysbeforelast) as Daysbeforelast
 from cte a
 inner join (select count(*) as Channelsingroup ,max(date) as Daysbeforelast 
 from table1 group by groupid) as  b 
 on a.groupid=b,groupid
相关问题