2012-06-14 3 views
0

В 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) поэтому я не заботиться о других сделок для этих ТПС

Строки, помеченные ** там, потому что (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 **.

Мне всегда нужно проверять только две лучшие транзакции для каждого ТПС.

Я новичок в SQL, и я потратил уже пару дней, чтобы попытаться выяснить, как я могу это достичь. Я считал, что я присоединяюсь к TransList, используя LIMIT или TOP или прогуливаясь по столу, но мне не удалось выполнить какое-либо из этих решений.

Может ли кто-нибудь помочь?

Edit:
Приведенная выше таблица была «извлечь», но в ответ на просьбу Андре, вот запрос:

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

Не могли бы вы опубликовать запрос SQL, который дает вам результат, который вы размещены выше? –

+0

Параметр, начинающийся с «Строки, отмеченные символом' * '...", даже не удаленно очищается. У нас нет самой туманной идеи о том, что действительно представляют ваш Start и End. Вам нужно прояснить правило, по которому что-то должно и не должно появляться. «Новейший для каждого TPN» достаточно прост, но как системный раздел начинается и заканчивается? Вы хотите, чтобы последний TPN для каждой уникальной комбинации Start/End? – Thomas

+0

@ Томас, извините. Хотя я был достаточно ясен, наверное, я был только надолго. Позвольте мне повторить попытку. Для каждой строки таблицы я хочу проверить самую последнюю комбинацию Start/End для каждого отдельного TPN; если комбинация Start/End соответствует определенному условию (например, Start = 6 и End = 3), тогда мне нужно также проверить предыдущую (в хронологическом порядке) комбинацию для той же TPN, прежде чем я смогу решить, буду ли я рассматривать это TPN или нет , Если нужно рассмотреть TPN, я затем выберу строку с последней комбинацией Start/End. надеюсь, что это яснее, но, вероятно, это не так ... – rodedo

ответ

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)) 
+0

Я пробую это; пока у меня есть некоторые проблемы, я попробую еще немного и вернусь с большим вопросом. Я предполагаю, что 'TRN' будет' TPN' согласно моей таблице, верно ?. – rodedo

+0

Мне пока не удалось использовать предложенный код как таковой, но он указал мне в правильном направлении, и теперь у меня есть промежуточный шаг, который будет делать для меня. поэтому рекомендуется и выбран в качестве ответа, спасибо! – rodedo

+0

Спасибо Rodedo. Рад помочь. –

Смежные вопросы