将每隔一行转换为列

时间:2019-02-10 02:37:22

标签: sql sql-server

我有一张这样的桌子:

time                tagid   stringvalue
2/9/2019 19:06:09   500     20945030
2/9/2019 17:54:13   500 
2/9/2019 16:02:26   500     20946065
2/9/2019 16:02:00   500 
2/9/2019 16:01:07   500     20936368
2/9/2019 15:29:13   500 
2/9/2019 14:58:15   500     20934130
2/9/2019 14:57:58   500 
2/9/2019 13:20:40   500     20934131

我想将其转换为SQL格式:

EndTime             tagid   stringvalue StartTime           tagid   stringvalue
2/9/2019 14:58:15   500     20934130    2/9/2019 14:57:58   500     20934130
2/9/2019 16:01:07   500     20936368    2/9/2019 15:29:13   500     20936368
2/9/2019 16:02:26   500     20946065    2/9/2019 16:02:00   500     20946065
2/9/2019 19:06:09   500     20945030    2/9/2019 17:54:13   500     20945030

基本上,我需要将每隔一行移到其他列。 你会怎么做?

4 个答案:

答案 0 :(得分:3)

假设您的实际数据与您向我们展示的一样好,并且每个开始记录都有匹配的结束记录,那么我们也许可以在这里使用ROW_NUMBER来摆脱困境:

WITH cte AS (
    SELECT time, tagid, stringvalue,
        ROW_NUMBER() OVER (ORDER BY time) - 1 AS rn
    FROM yourTable
)

SELECT
    MAX(time) AS EndTime,
    MAX(tagid) AS tagid,
    MAX(stringvalue) AS stringvalue,
    MIN(time) AS StartTime,
    MAX(tagid) AS tagid,
    MAX(stringvalue) AS stringvalue
FROM cte
GROUP BY
    rn / 2;

答案 1 :(得分:2)

一种可能的解决方案是仅LAG的时间为给定的StartTime制作EndTime,然后删除不包含stringvalue的行(包含{ {1}}值):

StartTime

输出:

SELECT EndTime,
       tagid,
       stringvalue,
       StartTime,
       tagId,
       stringvalue
FROM (SELECT time AS EndTime, tagid, stringvalue,
             LAG(time) OVER(ORDER BY tagid, time) AS StartTime
      FROM tags) t
WHERE stringvalue IS NOT NULL

如果您不希望未设置EndTime tagid stringvalue StartTime tagId stringvalue 09/02/2019 13:20:40 500 20934131 500 20934131 09/02/2019 14:58:15 500 20934130 09/02/2019 14:57:58 500 20934130 09/02/2019 16:01:07 500 20936368 09/02/2019 15:29:13 500 20936368 09/02/2019 16:02:26 500 20946065 09/02/2019 16:02:00 500 20946065 09/02/2019 19:06:09 500 20945030 09/02/2019 17:54:13 500 20945030 的行,只需添加

StartTime

AND StartTime IS NOT NULL 子句。

Demo on dbfiddle

答案 2 :(得分:0)

我可能会这样做:

with t as (
      select t.*, 
             row_number() over (partition by (case when stringvalue is null then 1 else 0 end)
                                order by time
                               ) as seqnum
      from <your table name here> t
     )
select t1.*, t2.*
from t t1 join
     t t2
     on t1.seqnum = t2.seqnum;

答案 3 :(得分:0)

SELECT Dateadd (s,t_stamp/1000, '1969/12/31 20:00:00') AS TimeStamp,a.tagid,a.stringvalue
From sqlt_data_5_2019_02 a 
join      sqlth_te b
ON        b.id =    a.tagid
where     tagpath in ('LL543')

WITH cte AS (
            SELECT Dateadd (s,t_stamp/1000, '1969/12/31 20:00:00') AS TimeStamp,a.tagid, a.stringvalue,
                ROW_NUMBER() OVER (ORDER BY t_stamp) - 1 AS rn
            FROM sqlt_data_5_2019_02 a 
            JOIN  sqlth_te b
            ON   b.id = a.tagid
            where     tagpath in ('LL543')
            )
SELECT
    MIN(TimeStamp) AS StartTime,
    MAX(TimeStamp) AS EndTime,
    MAX(tagid) AS tagid,
    MAX(stringvalue) AS stringvalue,
    MAX(tagid) AS tagid,
    MAX(stringvalue) AS stringvalue
FROM cte
GROUP BY  rn / 2;