SQL Query Pivot Data 2行为1

时间:2014-04-04 10:58:23

标签: sql tsql variables join

我尝试编写一个查询,将活动数据转换为摘要行。例如,输入数据是活动日期,描述和状态;如果它是信息性行,则启动,停止或为null。

这是数据格式的一个例子:

ID   | ActivityID | ActivityType | ActivityDate   | Status | Activity
----------------------------------------------------------------------
701  | 26         | Start        | 02/07/13 15:16 | 10     | Run Job
728  | 26         | No Change    | 05/07/13 09:30 | 20     | Running
859  | 26         | Stop         | 22/07/13 12:45 | 30     | Error
1064 | 26         | Start        | 10/08/13 13:26 | 11     | Restarted
1524 | 26         | Stop         | 28/08/13 10:19 | 31     | Error
1785 | 26         | Stop         | 07/09/13 11:48 | 31     | Error
2205 | 26         | Start        | 17/09/13 09:05 | 10     | Restarted
2528 | 26         | Start        | 14/10/13 17:56 | 11     | Restarted
2528 | 26         | Stop         | 25/10/13 20:47 | 32     | Completed

这是预期的结果:

ActivityID | Start_Type | Start_Date | Start_Status | Start_Activity | Stop_Type | Stop_Date | Stop_Status | Stop_Activity
---------------------------------------------------------------------------------
26 | Start | 02/07/13 15:16 | 10 | Run Job   | Stop | 22/07/13 12:45 | 30 | Error
26 | Start | 10/08/13 13:26 | 11 | Restarted | Stop | 28/08/13 10:19 | 31 | Error
26 | Start | 17/09/13 09:05 | 10 | Restarted | Stop | 25/10/13 20:47 | 32 | Done

我希望得到所有的开始,并将反应停止与activity_start_date等和activity_stop_date放在同一行。

我的问题是我希望每次开始后我都做了第一站,但是我也想忽略一个在它之前有一个开始的开始。对于瞬间启动,停止,停止,启动,启动,停止,启动将返回; Start Stop,Start Stop,Start null。

我尝试了一个左连接,在开始后加入第一站,但这也包括第二次开始匹配同一个停止两次。

我以为我需要临时表,但我认为这是不必要的。日期变量是否适用于第一个开始设置变量的位置,然后停止是设置变量的变量之后的第一个停止,下一个开始是新设置变量之后的第一个开始?

感谢您的帮助!

这是我到目前为止所做的:

SELECT
activity.ID,
activity.ActivityType                               AS StartActivityType,
activity.ActivityDate                               AS StartActivityDate,
activity.Status                                     AS StartStatus,
activity.Activity                                   AS StartActivity,
activity2.ActivityType                              AS StopActivityType,
activity2.ActivityDate                              AS StopActivityDate,
activity2.Status                                    AS StopStatus,
activity2.Activity                                  AS StopActivity

FROM tempdb..#TempTable activity

FULL OUTER JOIN #TempTable activity2
ON activity.ID = activity2.ID
AND activity2.ActivityType = 'Stop'
AND (activity2.ActivityDate > activity.ActivityDate)
AND (activity2.ActivityDate = ( SELECT MIN(activity3.ActivityDate)
FROM         tempdb..#TempTable activity3
WHERE activity.ID = activity2.ID
AND activity3.ActivityType = 'Stop'
AND activity3.ActivityDate > activity.ActivityDate))
WHERE activity.ActivityType = 'Start'

--does not have a start before
AND activity.ActivityDate > (   SELECT MAX(activity3.ActivityDate)
FROM tempdb..#TempTable activity2
                        WHERE activity2.PathwayID = activity.ID
                        AND activity2.ActivityType IN ('Stop','Start')
                        AND activity2.ActivityDate > activity.ActivityDate))

--AND activity2.ActivityDate != LAG(activity2.ActivityDate) OVER (ORDER BY activity.ActivityDate),
--AND activity.ActivityDate IS NULL

ORDER BY activity.ID ASC

2 个答案:

答案 0 :(得分:1)

select * from #TempTable a1
cross apply
(
select top 1 *
from
#TempTable a2
where
a2.ActivityType = 'Stop'
and a2.ActivityID = a1.ActivityID
and a2.ActivityDate > a1.ActivityDate
order by
a2.ActivityDate
) a2
where
a1.ActivityType = 'Start'
order by
a1.ActivityDate;

你的数据中有一些我不理解的奇怪之处,但是这应该会让你获得90%,并且它比尝试加入ActivityDate要清晰得多。

答案 1 :(得分:0)

shriop的查询几乎是正确的,它在跟随ActivityType = 'Start'的后续行(如2205和2528)时失败。对于那些需要删除重复行(具有相同ActivityType的行)。

如果OP使用SQLServer 2012或更高版本,可以使用LAG

完成
WITH DATA AS (
  SELECT ActivityID
       , ActivityType
       , ActivityDate
       , Status
       , Activity
       , LastActivity = LAG(ActivityType, 1, 'Stop') OVER (ORDER BY ActivityDate)
  FROM   Table1
  WHERE  ActivityType IN ('Start', 'Stop')
)
SELECT a1.ActivityID
     , Start_Type = a1.ActivityType
     , Start_Date = a1.ActivityDate
     , Start_Status = a1.Status
     , Start_Activity = a1.Activity
     , Stop_Type = a2.ActivityType
     , Stop_Date = a2.ActivityDate
     , Stop_Status = a2.Status
     , Stop_Activity = a2.Activity
FROM  DATA a1
CROSS apply (SELECT top 1 *
             FROM   Table1 a2
             WHERE  a2.ActivityType = 'Stop'
               AND a2.ActivityID = a1.ActivityID
               AND a2.ActivityDate > a1.ActivityDate
             ORDER BY a2.ActivityDate) a2
WHERE a1.ActivityType = 'Start'
  AND a1.LastActivity <> a1.ActivityType
ORDER BY a1.ActivityDate;

否则可以通过行编号和自联接来模拟LAG