获取相同列名称之间的单元格值

时间:2017-02-06 06:33:59

标签: sql sql-server

我之前曾问过如何获得可以看到的count of in-between rows from same column values here。提供的解决方案非常合适,但现在我需要额外的额外列来在allSTART之间获取 END 值。< / p>

样本表

/-----------------------------------------\
| ID ---------- Event -------- UserID ----|
| 1 ----------- START -------- 000001 ----|
| 2 ----------- START -------- 000002 ----|
| 3 ----------- END   -------- 000001 ----|
| 4 ----------- PL    -------- 000002 ----|
| 5 ----------- END   -------- 000002 ----|
\-----------------------------------------/

所需的输出

/---------------------------------------------------------\
| UserID ----------- Row Count ----------- rowbetweenvalue|
| 000001 ----------- 2         ----------- NULL           |
| 000002 ----------- 3         ----------- PL             |
\---------------------------------------------------------/

2 个答案:

答案 0 :(得分:2)

基于Dudu Markovitz提供的解决方案,其中一种方法就是:

创建并填充样本表(在将来的问题中保存此步骤)

DECLARE @T AS TABLE
(
    id int,
    event varchar(5),
    UserId char(6)
)

INSERT INTO @T VALUES
(1, 'START', '000001'),
(2, 'START', '000002'),
(3, 'END', '000001'),
(4, 'PL', '000002'),
(5, 'ZZ', '000002'),
(6, 'END', '000002')

将Dudu的答案封装成cte

;WITH cte AS
(
    select      UserID
               ,min(ID)     as from_ID
               ,max(ID)     as to_ID
               ,count(*)    as events

    from       (select      UserID,ID,Event
                           ,    count(case when Event in ('START','END') then 1 end) over 
                                (
                                    partition by    UserID 
                                    order by        Id 
                                    rows            unbounded preceding
                                )   
                            -   case when Event = 'END' then 1 else 0 end   as group_seq

                from        @T
                ) t

    group by    UserID
               ,group_seq

    having      min(case when Event = 'START' then 1 end) = 1
)

查询:

SELECT  UserId,
        From_Id,
        To_Id,
        Events As eventCount,
        STUFF(
        (
            SELECT ',' + event
            FROM @T
            WHERE UserId = cte.UserId 
            AND Id > from_ID
            AND Id < to_ID
            FOR XML PATH('')
        )
        , 1, 1, '') As events
FROM CTE    
ORDER BY UserID ,from_id

结果:

UserId  From_Id To_Id   eventCount  events
000001  1       3       2           NULL
000002  2       6       4           PL,ZZ

答案 1 :(得分:0)

以下是一个示例:

WITH sample_table(ID,Event,UserID)AS(
    SELECT 1,'START','000001' UNION ALL
    SELECT 2,'START','000002' UNION ALL
    SELECT 3,'END','000001' UNION ALL
    SELECT 4,'PL','000002' UNION ALL
    SELECT 5,'RC','000002' UNION ALL
    SELECT 6,'END','000002'
)
SELECT t1.UserID,2+ISNULL(LEN(r.v)-LEN(REPLACE(r.v,',','')),0) AS [Row Count],STUFF(r.v,1,1,'') AS rowbetweenvalue
FROM sample_table AS t1
CROSS APPLY(SELECT top 1 ID AS ENDID FROM sample_table AS tt WHERE tt.UserID=t1.UserID AND tt.ID>t1.ID AND tt.Event='END' ORDER BY ID) c
CROSS APPLY(SELECT ','+st.Event FROM sample_table AS st WHERE st.UserID=t1.UserID AND st.ID>t1.ID AND st.ID<c.ENDID FOR XML PATH('')) AS r(v)
WHERE t1.Event='START'
UserID Row Count            rowbetweenvalue
------ -------------------- ------------------------
000001 2                    NULL
000002 4                    PL,RC