我一直坚持这个问题已经有一段时间了。我觉得我很亲密,但是我有些遗漏。
交易可以有零个或多个TransactionErrors。我试图只显示所有交易一次,而且我也试图只显示最新的错误消息(如果有)。
SELECT [Transaction].[TransactionID]
,[FileName]
,[DestinationSystem]
,[CreatedOn]
,LEFT([TransactionError].[ErrorMessage], 300) AS LatestErrorMessage --Gets only the first 300 characters of the error message
FROM [WM01DB].[dbo].[Transaction]
INNER JOIN SourceSystem ON SourceSystem.SourceSystemId = Transaction.SourceSystemId
LEFT JOIN TransactionError ON TransactionError.TransactionId = Transaction.TransactionId
WHERE Transaction.CreatedOn >= '2014-08-01 00:00:00.000'
AND Transaction.CreatedOn < '2014-09-02 00:00:00.000'
ORDER BY [CreatedOn], [Transaction].[TransactionID]
当我运行此查询时,我得到了我想要的大部分结果,但是我得到了重复的事务,因为这些事务有多个TransactionErrors。它看起来像这样......
TransactionID FileName DestinationSystem CreatedOn LatestErrorMessage
18124 201408131541517937_DC_TEST_3339376-4.1.xml TEST 2014-08-18 18:31:19.993 U_BOL and Tracking Number are blank
18124 201408131541517937_DC_TEST_3339376-4.1.xml TEST 2014-08-18 18:31:19.993 FRT_CHG_TYPE is blank
18125 201408111521484448_DC_TEST_3339375-2.1.xml TEST 2014-08-19 16:04:58.467 NULL
18126 201408111521484448_DC_TEST_3339375-2.1.xml TEST 2014-08-19 16:09:00.467 NULL
呃......看起来不好的代码块...
如您所见,有重复的TransactionIDs,如18124所示。我希望18124只显示一次最新的错误消息。获取最新错误消息的唯一方法是使用特定TransactionID的最新TransactionErrorID ...
请帮忙! :(
答案 0 :(得分:1)
你可以使用 ROW_NUMBER()和 PARTITION BY 子句来实现它 -
SELECT [Transaction].[TransactionID]
,[FileName]
,[DestinationSystem]
,[CreatedOn]
,LEFT([TransactionError].[ErrorMessage], 300) AS LatestErrorMessage --Gets only the first 300 characters of the error message
,ROW_NUMBER() OVER (
PARTITION BY [Transaction].[TransactionID] ORDER BY [CreatedOn]
,[Transaction].[TransactionID] DESC
) AS SrNo
FROM [WM01DB].[dbo].[Transaction]
INNER JOIN SourceSystem ON SourceSystem.SourceSystemId = TRANSACTION.SourceSystemId
LEFT JOIN TransactionError ON TransactionError.TransactionId = TRANSACTION.TransactionId
WHERE TRANSACTION.CreatedOn >= '2014-08-01 00:00:00.000'
AND TRANSACTION.CreatedOn < '2014-09-02 00:00:00.000'
AND SrNo = 1
ORDER BY [CreatedOn]
,[Transaction].[TransactionID]
答案 1 :(得分:1)
SELECT A.[TransactionID]
,A.[FileName]
,A.[DestinationSystem]
,A.[CreatedOn]
,A.LatestErrorMessage
FROM (
SELECT [Transaction].[TransactionID]
,[FileName]
,[DestinationSystem]
,[CreatedOn]
,LEFT([TransactionError].[ErrorMessage], 300) AS LatestErrorMessage --Gets only the first 300 characters of the error message
,ROW_NUMBER() OVER (PARTITION BY [Transaction].[TransactionID] ORDER BY [CreatedOn] DESC) rn
FROM [WM01DB].[dbo].[Transaction]
INNER JOIN SourceSystem ON SourceSystem.SourceSystemId = [Transaction].SourceSystemId
AND [Transaction].CreatedOn >= '2014-08-01 00:00:00.000'
AND [Transaction].CreatedOn < '2014-09-02 00:00:00.000'
LEFT JOIN TransactionError ON TransactionError.TransactionId = [Transaction].TransactionId
)A
WHERE A.rn = 1
ORDER BY A.[CreatedOn], A.[TransactionID]
答案 2 :(得分:1)
我对Krishnraj Rana有类似的解决方案。但是,我认为您需要避免在WHERE子句中使用rowid过滤器,因为如果行为类似于内部联接,那将会产生:
; with Errors as
(SELECT [ErrorMessage]
, Row_Number() over (Partition By TransactionId order by TransactionErrorId Desc) as id
FROM TransactionError
)
SELECT [Transaction].[TransactionID]
,[FileName]
,[DestinationSystem]
,[CreatedOn]
,LEFT([ErrorMessage], 300) AS LatestErrorMessage --Gets only the first 300 characters of the error message
FROM [WM01DB].[dbo].[Transaction]
INNER JOIN SourceSystem ON SourceSystem.SourceSystemId = Transaction.SourceSystemId
LEFT JOIN Errors ON TransactionError.TransactionId = Transaction.TransactionId
and errors.id = 1
WHERE Transaction.CreatedOn >= '2014-08-01 00:00:00.000'
AND Transaction.CreatedOn < '2014-09-02 00:00:00.000'
ORDER BY [CreatedOn], [Transaction].[TransactionID]
答案 3 :(得分:1)
同样使用row_number()
,但按要求选择最后TransactionErrorId
(至少假设SQL Server 2005):
with x as (
select
t.[TransactionId],
[FileName],
[DestinationSytem],
[CreatedOn],
e.[ErrorMessage],
row_number() over (
partition by t.[TransactionId],
order by e.[TransactionErrorId] desc
) rn
from
[wm01db].[dbo].[Transaction] t
inner join
[dbo].[SourceSystem] s
on t.SourceSystemId = s.SourceSytemId
left outer join
[dbo].[TransactionError] e
on e.TransactionId = t.TransactionId
where
t.CreatedOn >= '2014-08-01 00:00:00.000' and
t.CreatedOn < '2014-09-02 00:00:00.000'
) select
[TransactionId],
[FileName],
[DestinationSytem],
[CreatedOn],
left([ErrorMessage], 300) as LastErrorMessage
from
x
where
rn = 1
order by
[CreatedOn],
[TransactionId] ;