根据同一个表中的其他行选择行

时间:2012-06-14 09:37:19

标签: sql-server

在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

那是:

  • 每个所选TPN的最新交易
  • 根据最新交易及/或其两项最新交易的条件选择TPN

标有*的行是因为(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

1 个答案:

答案 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))