SQL ROWNUMBER() 、WITH AS ()

在某些時候要從 SQL  Table 中取出資料,資料特性為不重複,且為

目前最新的狀態時,可以使用 ROWNUMBER () 來先進行排序的動作,

再做資料上的篩選;而取資料有時候會用到子查詢,子查詢的方式有許多種,

其中一種為使用  WITH AS () 的片段插入方式來做(CTE)。

假設今天有一張表,當中記錄著每天每台機器所生產的狀況,包含了日期、時間、班別、

相關的材料規格、重量等(表一):

另一張表則記錄著每台機器的資訊,像是規定的生產標準重量、

生產狀況等(表二):

今天想做一個查詢是--->找到每天當下的那個時刻,機器的生產情形。

首先,先針對表一做 ROWNUMBER(),先給予每筆資料進行排序

(WHER設定條件為2017年4月20日,機器為HJ03號,機器的重量不為0)

SELECT MItem AS 機器, YM AS 日期, HR AS 時間 , ROW_NUMBER() OVER(PARTITION BY MItem ORDER BY YM DESC,HR DESC) as 序號
FROM RowDataWReport 
WHERE MWeight<>'0' AND YM >= '20170420' AND MItem='HJ03'

再來,同樣對表二做日期格式的轉換(轉成一般的日期格式,目前為字串),以及選出在當下的時間點生產的重量,

SELECT W.MItem AS 機器, (substring (W.YM,1,4)+'-'+substring(W.YM,5,2)+'-'+substring(W.YM,7,2)+' '+substring (W.HR,1,2)+':'+substring(W.HR,3,2)+':'+substring(W.HR,5,2)) as 時間 ,
W.MWeight AS 實際重量

FROM RowDataWReport W

WHERE MItem='HJ03' and YM='20170420'

接著,針對表二做機器資料的選取,

SELECT machname as 機器,article as 名稱,BeSpec as 規格,status as 生產狀態,cast(cast(RefWt as decimal(10,3))*1000 as decimal(10,1)) as 基礎重量,
convert (decimal (10,2),RefHiPcntWt) as 上限值, convert (decimal (10,2),RefLowPcntWt) as 下限值 
FROM ProdStatus

有了上述的表格資訊後,接下來就是要整合在一起,並利用當中的資訊算出管制率(MAverageP)、

機器生產的狀況(介於上限值與下限值之間,105~100),

這時候就可使用 WITH AS() 的子查詢方式來做,完整的 SQL 如下:

With A as
(

SELECT MItem , YM , HR  , ROW_NUMBER() OVER(PARTITION BY MItem ORDER BY YM DESC,HR DESC) as RK
FROM RowDataWReport 
WHERE MWeight<>'0' AND YM >= '20170420' AND MItem='HJ03'
),
B AS
(

 W.MItem, (substring (W.YM,1,4)+'-'+substring(W.YM,5,2)+'-'+substring(W.YM,7,2)+' '+substring (W.HR,1,2)+':'+substring(W.HR,3,2)+':'+substring(W.HR,5,2)) as DateTime ,
W.MWeight FROM RowDataWReport W
JOIN ON W.Mitem = A.MItem and W.YM = A.YM and W.HR = A.HR and A.RK = 1
),
C AS
(

SELECT machname,article,BeSpec,status,cast(cast(RefWt as decimal(10,3))*1000 as decimal(10,1)) as StdWeight,
convert (decimal (10,2),RefHiPcntWt) as RefHiPcntWt, convert (decimal (10,2),RefLowPcntWt) as RefLowPcntWt 
FROM ProdStatus
)
SELECT Machname, article, BeSpec, StdWeight as RefHiWt, MWeight as RefLowWt, WCR as MAverageP, RefHiPcntWt, RefLowPcntWt,
case when WCR between 100 and 105 then '正常'
else '異常 'end as ProdStatus , status
FROM
(
SELECT B.*,C.*,
(select cast((B.MWeight-C.StdWeight)*100/C.StdWeight+105 as decimal (10,2))) as WCR
FROM STD
LEFT JOINON C.Machname = B.MItem
) R
ORDER BY machname

結果如下:

 ROWNUMBER()  OVER 的介紹,參考:

https://dotblogs.com.tw/joysdw12/2011/12/28/63596

WITH AS () 子查詢方法參考:

https://dotblogs.com.tw/dc690216/2010/02/02/13440