2017-05-04 89 views
0

要求:選擇兩個列對最近的不同記錄

我需要選擇[SKU][Store][Cost][Retail]爲每個不同的一個([SKU][Store])從[PriceChanges]組合,其中[Date]是最近的(不超過2017-04-25)和[Flag] = 0。我也只想選擇[PriceChanges]記錄,其中[Dept] = 100,通過[SKU]加入[Items]確定。

下面是來自我的表格的一些混淆的示例數據,但實際上我希望在我的結果集中取回約200萬條獨特記錄。

[PriceChanges](樣本):

+--------+-------+--------+--------+------------+------+ 
| SKU | Store | Cost | Retail | Date | Flag | 
+--------+-------+--------+--------+------------+------+ 
| 999999 | 1000 | 4.0850 | 4.09 | 2017-04-19 | 0 | 
| 999998 | 1001 | 4.0850 | 4.09 | 2017-04-19 | 1 | 
| 999999 | 1000 | 4.0650 | 4.07 | 2017-04-18 | 2 | 
+--------+-------+--------+--------+------------+------+ 

[Items](樣本):

+--------+------+ 
| SKU | Dept | 
+--------+------+ 
| 999999 | 100 | 
| 999998 | 101 | 
+--------+------+ 

我目前的解決方案:

SELECT s.[SKU], 
    s.[Store], 
    [Cost], 
    [Retail] 
FROM [PriceChanges] s 
    RIGHT JOIN 
(
    SELECT [SKU], 
     [Store], 
     [MaxDate] = MAX([Date]) 
    FROM [PriceChanges] 
     LEFT JOIN [Items] ON [PriceChanges].[SKU] = [Items].[SKU] 
               AND [Date] < '2017-04-25' 
               AND [Dept] = 100 
               AND [Flag] = 0 
    GROUP BY [SKU], 
      [Store] 
) m ON m.[SKU] = s.[SKU] 
    AND m.[Store] = s.[Store] 
    AND m.[MaxDate] = s.[Date]; 

上述解決方案似乎不起作用,因爲它會根據我們所擁有的不同SKU和商店的數量,返回比我預期的記錄多40%的記錄。什麼是寫這個查詢最有效的方法?

+0

請張貼期望的結果,也讓我們知道你正在使用哪個版本的sql-server。 –

+0

請根據您的樣本數據更新您的問題,並附上樣本預期結果。您可能需要添加一些附加示例數據來演示一些邊緣情況。例如,是否曾有過一個情況,即同一個(SKU/Store)組合可以有多於一行的Flag = 0? – pmbAustin

+0

謝謝,@vkp和@ pmbAustin。我正在出門,但會在幾個小時內嘗試更新您的建議。 –

回答

1

試試這個,

SELECT [SKU], 
    [Store], 
    [Cost], 
    [Retail] 
FROM 
(
    SELECT [SKU], 
     [Store], 
     [Cost], 
     [Retail], 
     ROW_NUMBER() OVER(PARTITION BY [SKU], 
           [Store] ORDER BY [Date] DESC) rn 
    FROM PriceChanges PC 
    WHERE [Date] <= '2017-04-25' 
     AND [Flag] = 0 
     AND EXISTS 
    (
     SELECT [SKU] 
     FROM [Items] i 
     WHERE pc.[SKU] = i.[SKU] 
      AND [DEPT] = 100 
    ) 
) t4 
WHERE rn = 1; 
+0

謝謝,@KumarHarsh。這看起來好像工作起來一樣(與Josh的答案看起來非常相似)。 –

+0

不,它不是類似的。我使用「Exists」子句。檢查性能。 – KumarHarsh

+0

你是對的。我對Josh的回答看到了大約31%的表現改善。不過,你的回答確實有一些錯別字。我剛剛提交了一個修改來修復它們。如果獲得批准,我會轉換我接受的答案。 –

2

如果你肯定只想要1行SKU和商店回來,你可以使用下面的查詢:

SELECT 
    [SKU] 
    ,[Store] 
    ,[Cost] 
    ,[Retail] 
FROM (
    SELECT 
    p.[SKU] 
    ,p.[Store] 
    ,p.[Cost] 
    ,p.[Retail] 
    ,ROW_NUMBER() OVER (PARTITION BY p.[SKU], p.[Store] ORDER BY p.[Date] DESC) as ranker 
    FROM [PriceChanges] p 
    JOIN [Items] i 
    ON p.[SKU] = i.[SKU] 
    WHERE 1=1 
    AND i.[Dept] = 100 
    AND p.[Flag] = 0 
    AND p.[Date] < '2017-04-25' 
) T 
WHERE 1=1 
    AND ranker = 1 
+0

爲什麼'WHERE 1 = 1'? – Lucero

+0

啊,這只是習慣。見https://dba.stackexchange.com/questions/54954/why-use-where-1-or-where-1-1 –

+0

這一個產生了我期待的記錄的確切數量。謝謝! –