我是一张新手海报,但是花了很多时间在这里研究答案。我无法弄清楚如何使用SQL Server 2008 R2创建一个SQL结果集,该结果集应该使用更现代版本的超前/滞后。我试图根据一列的序列聚合数据,但每个序列中可能有不同数量的实例。我知道序列已经结束的唯一方法是下一行的序列号较低。所以它可能会出现1-2,1-2-3-4,1-2-3,我必须弄清楚如何制作3个聚合。
源数据是连接的表,看起来像这样(请帮我格式化):
recordID instanceDate moduleID iResult interactionNum
1356 10/6/15 16:14 1 68 1
1357 10/7/15 16:22 1 100 2
1434 10/9/15 16:58 1 52 1
1435 10/11/15 17:00 1 60 2
1436 10/15/15 16:57 1 100 3
1437 10/15/15 16:59 1 100 4
我需要找到一种方法,根据最后一列中的值,将前两行与最后4行分开。
我最想得到的是一个看起来像这样的结果集,它根据分组对iResult列进行平均,并从分组中获取第一个instanceDate:
instanceDate moduleID iResult
10/6/15 1 84
10/9/15 1 78
如果我能找到一种分离组的方法,我可以使用MIN和AVG进行聚合以获得此结果。数据按instanceDate排序(请忽略此处的日期格式)然后当查询找到interactionNum为< =而不是前一行的行时(通常会以' 1& #39;但并非总是如此,所以最好只是在较低或相等的整数值上分开。)
这是我到目前为止的查询(包括提供上述数据集的连接):
SELECT
X.*
FROM
(SELECT TOP 100 PERCENT
instanceDate, b.ModuleID, iResult, b.interactionNum
FROM
(firstTable a
INNER JOIN
secondTable b ON b.someID = a.someID)
WHERE
a.someID = 2
AND b.otherID LIKE 'xyz'
AND a.ModuleID = 1
ORDER BY
instanceDate) AS X
OUTER APPLY
(SELECT TOP 1
*
FROM
(SELECT
instanceDate, d.ModuleID, iResult, d.interactionNum
FROM
(firstTable c
INNER JOIN
secondTable d ON d.someID = c.someID)
WHERE
c.someID = 2
AND d.otherID LIKE 'xyz'
AND c.ModuleID = 1
AND d.interactionNum = X.interactionNum
AND c.instanceDate < X.instanceDate) X2
ORDER BY
instanceDate DESC) Y
WHERE
NOT EXISTS (SELECT Y.interactionNum INTERSECT SELECT X.interactionNum)
但是这会返回一个像这样的中间结果集:
instanceDate ModuleID iResult interactionNum
10/6/15 16:10 1 68 1
10/6/15 16:14 1 100 2
10/15/15 16:57 1 100 3
10/15/15 16:59 1 100 4
问题是interactionNum 3,4不属于此结果集。当我遍历此查询时,它们将进入下一个结果集。如何在这次迭代中将它们排除在结果集之外?我需要此查询的结果集才能包含前两行,&#39;看到&#39;第3行的源数据具有较低的interactionNum值而不是第2行具有的值。
答案 0 :(得分:5)
不确定应该使用什么ModuleID,但我想你正在寻找这样的东西:
select min (instanceDate), [moduleID], avg([iResult])
from (
select *,row_number() over (partition by [moduleID] order by instanceDate) as RN
from Table1
) X
group by [moduleID], RN - [interactionNum]
这里的想法是为每个moduleid创建一个带有row_number的运行编号,然后使用它与InteractionNum之间的差异作为分组标准。
中的示例答案 1 :(得分:0)
这是我的解决方案,虽然应该说,但我认为@JamesZ答案更清晰。
我创建了一个名为newinstance
的新字段,只要您的instanceNumber
为1,就会为1.我创建了一个名为sum(newinstance)
的滚动rollinginstance
来分组。
将上次选择更改为SELECT * FROM cte2
以显示我添加的所有字段。
IF OBJECT_ID('tempdb..#tmpData') IS NOT NULL
DROP TABLE #tmpData
CREATE TABLE #tmpData (recordID INT, instanceDate DATETIME, moduleID INT, iResult INT, interactionNum INT)
INSERT INTO #tmpData
SELECT 1356,'10/6/15 16:14',1,68,1 UNION
SELECT 1357,'10/7/15 16:22',1,100,2 UNION
SELECT 1434,'10/9/15 16:58',1,52,1 UNION
SELECT 1435,'10/11/15 17:00',1,60,2 UNION
SELECT 1436,'10/15/15 16:57',1,100,3 UNION
SELECT 1437,'10/15/15 16:59',1,100,4
;WITH cte1 AS
(
SELECT *,
CASE WHEN interactionNum=1 THEN 1 ELSE 0 END AS newinstance,
ROW_NUMBER() OVER(ORDER BY recordID) as rowid
FROM #tmpData
), cte2 AS
(
SELECT *,
(select SUM(newinstance) from cte1 b where b.rowid<=a.rowid) as rollinginstance
FROM cte1 a
)
SELECT MIN(instanceDate) AS instanceDate, moduleID, AVG(iResult) AS iResult
FROM cte2
GROUP BY moduleID, rollinginstance