在SQL Server中,我有一个表(我们称之为TransList
),如下所示:
TPN Start End TDate DoneBy
10 6 7 2003-03-17 14:48:42.750 User2 *
10 1 6 2003-03-13 08:02:09.317 User3
11 3 6 2003-03-21 08:15:45.410 User3 ** yes
11 6 3 2003-03-13 08:13:13.920 User4 <--
11 5 6 2003-03-08 17:39:51.460 User4
12 13 3 2003-03-19 10:58:23.187 User8 *
12 6 13 2003-03-17 14:48:42.750 User7
12 3 6 2003-03-13 08:02:09.317 User6
12 1 3 2003-03-01 14:09:17.167 User1
13 3 6 2003-03-19 10:58:23.187 User1 *** no
13 1 3 2003-03-01 14:09:17.167 User2 <--
14 3 6 2003-03-21 08:15:45.410 User5 ** yes
14 13 3 2003-03-13 08:13:13.920 User6 <--
14 6 13 2003-03-08 17:39:51.460 User7
15 6 3 2003-03-17 14:48:42.750 User2 *
15 1 6 2003-03-13 08:02:09.317 User3
这是一个非常复杂的查询的结果,它连接两个单独的SELECT语句,每个语句连接几个表。行按TPN ASC, TDate DESC
排序。
我现在要过滤此表并获取:
TPN Start End TDate DoneBy
10 6 7 2003-03-17 14:48:42.750 User2
11 3 6 2003-03-21 08:15:45.410 User3
12 13 3 2003-03-19 10:58:23.187 User8
14 3 6 2003-03-21 08:15:45.410 User5
15 6 3 2003-03-17 14:48:42.750 User2
那是:
标有*
的行是因为(Start=6 and End=7) or (Start=13 and End=3) or (Start=6 and End=3)
因此我不关心这些TPN的其他交易
标有**
的行是因为(Start=3 and End=6) and for previous transaction (Start=6 and End=3)
标有***
的行不,因为(Start=3 and End=6) but for previous transaction is not (Start=6 and End=3)
我可能需要根据哪个用户执行上一个事务和/或*
和**
具有更复杂的逻辑条件来进一步选择(状态机很复杂,我还没有完成检查它)***
始终是not **
。
我总是只需要检查每个TPN的前2个交易。
我是SQL的新手,我花了几天时间试图弄清楚如何实现这一目标。我考虑过自我加入TransList
,使用LIMIT或TOP或走过桌子,但我没有设法使这个解决方案有效。
有人可以帮忙吗?
修改:
上面的表格是“摘录”,但为了回应安德烈的请求,这里是查询:
SELECT Items.[TPN],
[StartStatus],
[EndStatus],
[TransactionDate],
[TransDoneBy],
[CurrentStatus],
[Title],
[Severity],
[LastChangeDate],
[ChangeDoneBy],
[Planned],
[Remaining]
FROM
(SELECT WORKITEM as 'TPN',
TFIELDCHANGE.NEWSYSTEMOPTIONID as 'StartStatus',
TFIELDCHANGE.OLDSYSTEMOPTIONID as 'EndStatus',
THISTORYTRANSACTION.LASTEDIT as 'TransactionDate',
trans_person.LASTNAME as 'TransDoneBy'
FROM dbo.THISTORYTRANSACTION JOIN dbo.TFIELDCHANGE ON (dbo.THISTORYTRANSACTION.OBJECTID = dbo.TFIELDCHANGE.HISTORYTRANSACTION)
JOIN dbo.TPERSON trans_person ON (dbo.THISTORYTRANSACTION.CHANGEDBY = trans_person.PKEY)
WHERE dbo.TFIELDCHANGE.FIELDKEY = 4 -- Only transactions regarding status
) Transactions
JOIN
(SELECT WORKITEMKEY as 'TPN',
TSTATE.LABEL as 'CurrentStatus',
PACKAGESYNOPSYS as 'Title',
TSEVERITY.LABEL as 'Severity',
TWORKITEM.LASTEDIT as 'LastChangeDate',
item_person.LASTNAME as 'ChangeDoneBy',
max(CASE TATTRIBUTEVALUE.FIELDKEY WHEN 60 THEN TATTRIBUTEVALUE.INTEGERVALUE END) as 'Planned',
max(CASE TATTRIBUTEVALUE.FIELDKEY WHEN 72 THEN TATTRIBUTEVALUE.INTEGERVALUE END) as 'Remaining'
FROM dbo.TWORKITEM JOIN dbo.TSTATE ON (dbo.TWORKITEM.STATE = dbo.TSTATE.PKEY)
JOIN dbo.TSEVERITY ON (dbo.TWORKITEM.SEVERITYKEY = dbo.TSEVERITY.PKEY)
JOIN dbo.TPERSON item_person ON (dbo.TWORKITEM.CHANGEDBY = item_person.PKEY)
JOIN dbo.TATTRIBUTEVALUE ON (dbo.TWORKITEM.WORKITEMKEY = dbo.TATTRIBUTEVALUE.WORKITEM)
WHERE dbo.TWORKITEM.STATE = 2 OR -- Current state: analyzed
dbo.TWORKITEM.STATE = 3 OR -- Current state: assigned
dbo.TWORKITEM.STATE = 4 OR -- Current state: suspended
dbo.TWORKITEM.STATE = 6 OR -- Current state: implemented
dbo.TWORKITEM.STATE = 7 OR -- Current state: verified
dbo.TWORKITEM.STATE = 13 -- Current state: verifying
GROUP BY WORKITEMKEY,
TSTATE.LABEL,
PACKAGESYNOPSYS,
TSEVERITY.LABEL,
TWORKITEM.LASTEDIT,
item_person.LASTNAME
) Items
ON Items.TPN = Transactions.TPN
ORDER BY Items.[TPN] ASC, [TransactionDate] DESC
答案 0 :(得分:2)
看来你正在寻找一种比较集团最新交易与其前身的一般方法。
这可以使用ROW_NUMBER()
函数和这样的自联接来完成:
SELECT foo
FROM (SELECT foo,
Row_number() OVER (PARTITION BY TRN ORDER BY TDate) AS RN
FROM TranTable) AS Latest
LEFT JOIN (SELECT foo,
Row_number() OVER (PARTITION BY TRN ORDER BY TDate) AS RN
FROM TranTable) AS Previous
ON Latest.RN = Previous.RN - 1
WHERE Latest.RN = 1 /* Get only the latest */
OR (/* your criteria for two latest */ AND Latest.RN IN (1,2))