2017-02-08 15 views
0

以下は日常の在庫レベルです。曜日のレコードがない場合は、その日に在庫がゼロだったことを意味します。在庫レベルの計算 - SQL

Week | Product | Inventory on first day of the week | Inventory on last day of the week | No of days product was available 
1 A 10 0 4 
2 A 0 2 4 

の下に、私はインタビューの中で、この質問をしたし、これは例えばのために、この場合、インベントリに第三、第六及び第一週の7日目にゼロであった

Week | Day of the Week | Product | Inventory 
1 1 A 10 
1 2 A 20 
1 4 A 5 
1 5 A 5 
2 2 A 20 
2 3 A 15 
2 4 A 5 
2 7 A 2 

私が探していますが出力されます私が思いついたものインタビュアーは私に、より良いアプローチがあると言っていました。そう。任意の提案は歓迎

WITH CTE_Inventory_Rank 
    AS (SELECT Week, 
       [Day of the Week], 
       Product, 
       Inventory, 
       RANK() OVER(PARTITION BY WEEK ORDER BY [Day of the Week]) RankAsc, 
       RANK() OVER(PARTITION BY WEEK ORDER BY [Day of the Week] DESC) RankDesc 
     FROM Inventory), 
    CTE_Inventory 
    AS (SELECT WEEK, 
       Product, 
       COUNT(*) [No of days product was available] 
     FROM Inventory 
     GROUP BY WEEK, 
        PRODUCT) 
    SELECT I.Week, 
      I.Product, 
      CASE 
       WHEN first.[Day of the Week] = 1 
       THEN first.Inventory 
       ELSE 0 
      END [Inventory on first day of the week], 
      CASE 
       WHEN last.[Day of the Week] = 7 
       THEN last.Inventory 
       ELSE 0 
      END [Inventory on first day of the week], 
      i.[No of days product was available] 
    FROM CTE_INVENTORY I 
      JOIN CTE_Inventory_Rank first ON I.week = first.week 
              AND I.Product = first.Product 
              AND first.RankAsc = 1 
      JOIN CTE_Inventory_Rank last ON I.week = last.week 
              AND I.Product = last.Product 
              AND last.RankDesc = 1; 
+2

? –

答えて

1

それは本当に彼がより良く意味するかによって異なります。より良いパフォーマンス、短い、かなり? postgresのため

ライブ例: http://rextester.com/EMKQRJ98261

create table Inventory (week integer, dow integer, product varchar, inventory integer); 

insert into Inventory (week, dow, product, inventory) VALUES 
(1,1,'A',10), 
(1,2,'A',20), 
(1,4,'A',5), 
(1,5,'A',5), 
(2,2,'A',20), 
(2,3,'A',15), 
(2,4,'A',5), 
(2,7,'A',2); 


SELECT week, 
     product, 
     MAX(inv_first_dow) as "Inventory on first day of the week", 
     MAX(inv_last_dow) as "Inventory on last day of the week", 
     COUNT(*) as "No of days product was available" 
FROM (
    SELECT week, 
     product, 
     CASE WHEN dow.dow = 1 THEN inventory ELSE 0 END AS inv_first_dow, 
     CASE WHEN dow.dow = 7 THEN inventory ELSE 0 END AS inv_last_dow 
    FROM unnest(array[1,2,3,4,5,6,7]) as dow 
    JOIN Inventory ON Inventory.dow = dow.dow 
) a 
GROUP BY week, product 
ORDER BY week 

これは、MS SQLサーバのバージョンです:http://rextester.com/NQW89990 DBMSは、使用している

WITH unnest(dow) AS (SELECT 1 UNION ALL SELECT dow+1 FROM unnest WHERE dow < 7) 
SELECT week, 
     product, MAX(inv_first_dow) as "Inventory on first day of the week", 
     MAX(inv_last_dow) as "Inventory on last day of the week", 
     COUNT(*) as "No of days product was available" 
FROM (
    SELECT week, 
     product, 
     CASE WHEN dow.dow = 1 THEN inventory ELSE 0 END AS inv_first_dow, 
     CASE WHEN dow.dow = 7 THEN inventory ELSE 0 END AS inv_last_dow 
    FROM unnest as dow 
    JOIN Inventory ON Inventory.dow = dow.dow 
) a 
GROUP BY week, product 
ORDER BY week 
+0

私はより良いパフォーマンスで1つを探していました。あなたの例は素晴らしいです。これは、テーブルに複数回参加しないため、より高速なパフォーマンスを提供するはずです。しかし、私はMS SQL Serverで不必要な機能を持っていないので、私はMS SQLでこのシンプルなソリューションを実装する方法を考えています – Sathya

+0

私は行セットに配列を変換するために使用されます。次のように再帰CTEを使用することで同様の結果が得られます。WITH unnest(dow)AS(SELECT 1 UNION ALL SELECT dow + 1 FROM unnest WHERE dow <7)SELECT dow FROM unnest; –

関連する問題