Sql-Server

需要幫助優化查詢

  • March 23, 2017

這是我第一次在 StackExchange 上發帖。我正在研究如何使用 SQL 編寫查詢,以便在我的工作場所我們可以為我們的庫存軟體編寫更深入的自定義報告。我在我們學區交通部的商店工作,訂購零件並監控其庫存。

我只是通過Google、Microsoft文章和YouTube上的影片系列等線上資源開始學習SQL,如果我的SQL語法不好,請原諒我;我有更多的時間在家起草報告(即遠離我需要測試這些報告的數據庫!)。我能夠從我們的軟體製造商那裡獲得一份 PDF,詳細說明數據庫中的哪些表連接到哪個表以及連接到哪裡。

然而,正如對一個如此陌生的人所期望的那樣,我在語法方面遇到了很多困難。

(對於那些想知道我是否已經聯繫過軟體製造商的技術支持的人,我已經與他們進行了數十次交談,涉及許多很多主題,其中之一是獲得幫​​助編寫自定義報告,在那個部門,我至少 90% 確信只有一個人真正關心學習如何導航 SQL。)

不管怎樣——我正在起草的一份報告(這也是我今天來到這裡的原因)的目標是讓我們能夠預測未來幾季的零件使用情況。它將使用我猜想可以被描述為遞歸查詢的內容,並將以三個月為間隔將使用的每個不同部分的數量相加。(但是,當然,這個間隔可以擴大到兩個甚至三個月,以便更好地表示長時間的使用。)完成後,這個查詢的一個方面也可以被複製用於編寫第二份報告將每季度自動更新每個零件所需的最小和最大庫存 - 該軟體的另一個急需的功能!

我覺得我實際上可以編寫一個過程並聲明變數,這樣我就不必將子查詢全部寫回十二次,而只需要定義求和之間的間隔,一個正整數。

這是我將不得不使用的兩個表和相關的列:

工作訂單

RecordID LONG (PK)
RelDateTime Date/Time

沃帕

RecordID LONG (FK)
PartNumber TEXT
Description TEXT
Qty DECIMAL
InstDate Date/Time

部分

PartNumber TEXT
Descrip TEXT

(WoPart 中還有另一個欄位,WoPart.InstDate,我最初認為這意味著我不需要 WorkOrders 表,我花了很多時間試圖弄清楚如何正確編寫我的查詢,這樣它實際上會給我任何東西但是一個空值-唉,該列似乎並沒有真正做任何事情;我在該表的任何行中都找不到該列的單個非空值。我當時想,這可能與何時有關如果有問題的元件曾經被定義為具有保修(我們最終只是勉強在我們的數據庫中推出的一項功能!),則安裝該元件。不幸的是,其他查詢得出結論,這似乎也不是這種情況。再次- 這就是我在這裡的原因。)

在這一點上,我認為我需要編寫一個內部查詢,首先在 tbl.WorkOrders 中搜尋所需時間範圍內的那些 RelDateTime 值(比如說 2016 年 12 月 1 日到 2017 年 2 月 1 日)。從那裡 tbl.WorkOrders 在其 RecordID 列上有一個與 tbl.WoPart 的內部連接,這樣我們就可以讓外部查詢提取那些使用相關元件的 WoPart RecordID,並使用表達式 SUM(Qty)。

這就是我迄今為止所擁有的。它還沒有完成,我肯定看起來很困惑(特別是考慮到我今天不得不重新開始!)也許它只需要……徹底翻過來……:

DECLARE @Interval INT > 0

SET @Interval = 1

SELECT      WoPart.PartNumber AS [Part Number]
          ,Parts.Descript AS [Description]
          ,SUM(SELECT Qty
               FROM   WoPart
               WHERE  PartNumber = PartNumber) AS [MONTH(GETDATE()) + '/' + RIGHT(YEAR(GETDATE()),2)]
FROM       WoPart
INNER JOIN WorkOrders
ON         WorkOrders.RecordID = WoPart.RecordID
INNER JOIN Parts
ON         WoPart.PartNumber = Parts.PartNumber
WHERE      RelDateTime BETWEEN DATEADD(MONTH, -2 * @Interval, GETDATE())
                              AND
                              DATEADD(MONTH, -1 * @Interval, GETDATE())

所需的輸出應如下所示:

+--------------+---------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+
| Part Number  |  Description  | Qtr 1 | Qtr 2 | Qtr 3 | Qtr 4 | 2014  | Qtr 1 | Qtr 2 | Qtr 3 | Qtr 4 | 2015  | Qtr 1 | Qtr 2 | Qtr 3 | Qtr 4 | 2016  |
+--------------+---------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+
| BD7250       | OIL FILTER    |    12 |    13 |    11 |    14 |    50 |    14 |    12 |    15 |    13 |    54 |    14 |    16 |    13 |    17 |    60 |
| ...          | ...           | ...   | ...   | ...   | ...   | ...   | ...   | ...   | ...   | ...   | ...   | ...   | ...   | ...   | ...   | ...   |

根據選定的日期添加盡可能多的 SUM(CASE。

SELECT      WoPart.PartNumber AS [Part Number]
          ,Parts.Descript AS [Description]
          ,SUM(CASE WHEN YEAR(RelDateTime) = 2014 
                     AND DATEPART(QQ, RelDateTime) = 1 THEN Qty ELSE 0 END) AS 'Qtr1/14'
          ,SUM(CASE WHEN YEAR(RelDateTime) = 2014 
                     AND DATEPART(QQ, RelDateTime) = 2 THEN Qty ELSE 0 END) AS 'Qtr2/14'
          ,SUM(CASE WHEN YEAR(RelDateTime) = 2014 
                     AND DATEPART(QQ, RelDateTime) = 3 THEN Qty ELSE 0 END) AS 'Qtr3/14'
          ,SUM(CASE WHEN YEAR(RelDateTime) = 2014 
                     AND DATEPART(QQ, RelDateTime) = 4 THEN Qty ELSE 0 END) AS 'Qtr4/14'
          ,SUM(CASE WHEN YEAR(RelDateTime) = 2014 THEN Qty ELSE 0 END) AS '2014'
          ,SUM(CASE WHEN YEAR(RelDateTime) = 2015 
                     AND DATEPART(QQ, RelDateTime) = 1 THEN Qty ELSE 0 END) AS 'Qtr1/15'
          ,SUM(CASE WHEN YEAR(RelDateTime) = 2015 
                     AND DATEPART(QQ, RelDateTime) = 2 THEN Qty ELSE 0 END) AS 'Qtr2/15'
          ,SUM(CASE WHEN YEAR(RelDateTime) = 2015 
                     AND DATEPART(QQ, RelDateTime) = 3 THEN Qty ELSE 0 END) AS 'Qtr3/15'
          ,SUM(CASE WHEN YEAR(RelDateTime) = 2015 
                     AND DATEPART(QQ, RelDateTime) = 4 THEN Qty ELSE 0 END) AS 'Qtr4/15'
          ,SUM(CASE WHEN YEAR(RelDateTime) = 2015 THEN Qty ELSE 0 END) AS '2015'
          ,SUM(CASE WHEN YEAR(RelDateTime) = 2016 
                     AND DATEPART(QQ, RelDateTime) = 1 THEN Qty ELSE 0 END) AS 'Qtr1/16'
          ,SUM(CASE WHEN YEAR(RelDateTime) = 2016 
                     AND DATEPART(QQ, RelDateTime) = 2 THEN Qty ELSE 0 END) AS 'Qtr2/16'
          ,SUM(CASE WHEN YEAR(RelDateTime) = 2016 
                     AND DATEPART(QQ, RelDateTime) = 3 THEN Qty ELSE 0 END) AS 'Qtr3/16'
          ,SUM(CASE WHEN YEAR(RelDateTime) = 2016 
                     AND DATEPART(QQ, RelDateTime) = 4 THEN Qty ELSE 0 END) AS 'Qtr4/16'
          ,SUM(CASE WHEN YEAR(RelDateTime) = 2016 THEN Qty ELSE 0 END) AS '2016'
FROM       WoPart
INNER JOIN WorkOrders
ON         WorkOrders.RecordID = WoPart.RecordID
INNER JOIN Parts
ON         WoPart.PartNumber = Parts.PartNumber
WHERE      RelDateTime >= CAST('20140101' AS DATETIME)
AND        RelDateTime <  CAST('20170101' AS DATETIME)
GROUP BY   WoPart.PartNumber, Parts.Descript;

引用自:https://dba.stackexchange.com/questions/167821