Sql 多次连接到同一个表时的条件连接和查询优化
我们的数据库中有两个表。查询中的主表是Asset。它与名为AssetListing的表具有一对多关系。 AssetListing表中有多个日期和数字字段,我们当前有一个报告,用于获取每个日期中的一个,在某些情况下,还可以从AssetListing表中获取日期不为空的数值。需要注意的是,在每种情况下,如果特定日期不为空,我们都希望获得与最近的AssetListingId(AssetListing上的PK)关联的日期。查询当前如下所示:Sql 多次连接到同一个表时的条件连接和查询优化,sql,sql-server,query-optimization,Sql,Sql Server,Query Optimization,我们的数据库中有两个表。查询中的主表是Asset。它与名为AssetListing的表具有一对多关系。 AssetListing表中有多个日期和数字字段,我们当前有一个报告,用于获取每个日期中的一个,在某些情况下,还可以从AssetListing表中获取日期不为空的数值。需要注意的是,在每种情况下,如果特定日期不为空,我们都希望获得与最近的AssetListingId(AssetListing上的PK)关联的日期。查询当前如下所示: SELECT A.AssetNumber ,
SELECT A.AssetNumber
, CLP.CurrentListPrice
, CLP.CurrentListPriceDate
, ListingExpirationDate = LXP.ExpirationDate
, LPC.ListPriceChange
, LPC.ListPriceChangeDate
FROM Asset A
LEFT JOIN
(
SELECT AssetNumber
, AssetListingId
, CurrentListPrice
, CurrentListPriceDate
, ROW_Num = ROW_NUMBER() OVER (PARTITION BY AssetNumber ORDER BY AssetListingId DESC)
FROM [dbo].AssetListing WITH (NOLOCK)
WHERE CurrentListPrice IS NOT NULL
) CLP ON CLP.AssetNumber = A.AssetNumber AND CLP.ROW_NUM = 1
LEFT JOIN
(
SELECT AssetNumber
, AssetListingId
, ExpirationDate
, ROW_Num = ROW_NUMBER() OVER (PARTITION BY AssetNumber ORDER BY AssetListingId DESC)
FROM [dbo].AssetListing WITH (NOLOCK)
WHERE ExpirationDate IS NOT NULL
) LXP ON LXP.AssetNumber = A.AssetNumber AND LXP.ROW_NUM = 1
LEFT JOIN
(
SELECT AssetNumber
, AssetListingId
, CurrentListPrice
, ListPriceChange
, ListPriceChangeDate
, ROW_Num = ROW_NUMBER() OVER (PARTITION BY AssetNumber ORDER BY AssetListingId DESC)
FROM [dbo].AssetListing WITH (NOLOCK)
WHERE ListPriceChange IS NOT NULL
) LPC ON LPC.AssetNumber = A.AssetNumber AND LPC.ROW_NUM = 1
必须有一种方法可以通过一个连接来实现这一点,但我不确定如何进行。
我们需要每个连接的日期,在某些情况下,我们还需要一个数值。
如何优化此查询?试试看,这样做的目的是最大限度地利用基于行号的每个资产编号应该只有一个结果
SELECT A.AssetNumber
, CurrentListPrice = MAX(CASE WHEN CPRN = 1 THEN CurrentListPrice END)
, CurrentListPriceDate = MAX(CASE WHEN CPRN = 1 THEN CurrentListPriceDate END)
, ListingExpirationDate = MAX(CASE WHEN EPRN = 1 THEN ExpirationDate END)
, ListPriceChange = MAX(CASE WHEN EPRN = 1 THEN ExpirationDate END)
, ListPriceChangeDate = MAX(CASE WHEN EPRN = 1 THEN ExpirationDate END)
FROM Asset A
JOIN (
SELECT AssetNumber
, AssetListingId
, CurrentListPrice
, CurrentListPriceDate
, ExpirationDate
, ListPriceChange
, ListPriceChangeDate
, CPRN = CASE WHEN CurrentListPrice IS NOT NULL
THEN ROW_NUMBER() OVER (PARTITION BY AssetNumber ORDER BY AssetListingId DESC) END
, EPRN = CASE WHEN ExpirationDate IS NOT NULL
THEN ROW_NUMBER() OVER (PARTITION BY AssetNumber ORDER BY AssetListingId DESC) END
, LPRN = CASE WHEN ListPriceChange IS NOT NULL
THEN ROW_NUMBER() OVER (PARTITION BY AssetNumber ORDER BY AssetListingId DESC) END
FROM dbo.AssetListing WITH (NOLOCK)
) AL ON AL.AssetNumber = A.AssetNumber
GROUP BY A.AssetNumber
实际上,连接在这里看起来没有必要,但我把它留了下来,以防有一些简化。试试看,这样做的想法是,根据行号,每个资产编号最多只能有一个结果
SELECT A.AssetNumber
, CurrentListPrice = MAX(CASE WHEN CPRN = 1 THEN CurrentListPrice END)
, CurrentListPriceDate = MAX(CASE WHEN CPRN = 1 THEN CurrentListPriceDate END)
, ListingExpirationDate = MAX(CASE WHEN EPRN = 1 THEN ExpirationDate END)
, ListPriceChange = MAX(CASE WHEN EPRN = 1 THEN ExpirationDate END)
, ListPriceChangeDate = MAX(CASE WHEN EPRN = 1 THEN ExpirationDate END)
FROM Asset A
JOIN (
SELECT AssetNumber
, AssetListingId
, CurrentListPrice
, CurrentListPriceDate
, ExpirationDate
, ListPriceChange
, ListPriceChangeDate
, CPRN = CASE WHEN CurrentListPrice IS NOT NULL
THEN ROW_NUMBER() OVER (PARTITION BY AssetNumber ORDER BY AssetListingId DESC) END
, EPRN = CASE WHEN ExpirationDate IS NOT NULL
THEN ROW_NUMBER() OVER (PARTITION BY AssetNumber ORDER BY AssetListingId DESC) END
, LPRN = CASE WHEN ListPriceChange IS NOT NULL
THEN ROW_NUMBER() OVER (PARTITION BY AssetNumber ORDER BY AssetListingId DESC) END
FROM dbo.AssetListing WITH (NOLOCK)
) AL ON AL.AssetNumber = A.AssetNumber
GROUP BY A.AssetNumber
连接在这里看起来并没有必要,但我把它留了下来,以防万一会有一些简化