SELECT VipMember_CreatedDateTime, VipMember_Id FROM dbo.VipMember WITH (READCOMMITTED) WHERE VipMember_ValidFlag =1 AND VipMember_CreatedDateTime >=@firstDayOfMonth-- 10/1 00:00 AND VipMember_CreatedDateTime < DATEADD(DAY, 1, @firstDayOfMonth); -- 10/2 00:00
WHILE @month<=12 BEGIN SET@startDate= DATEFROMPARTS(@year, @month, 1); SET@endDate= DATEADD(DAY, 1, @startDate);
INSERTINTO #VipMember_FirstDay(CreateDate, Id) SELECT VipMember_CreatedDateTime, VipMember_Id FROM VipMember(NOLOCK) WHERE VipMember_CreatedDateTime >=@startDate AND VipMember_CreatedDateTime <@endDate;
SET@month=@month+1; END
SELECT*FROM #VipMember_FirstDay;
1 2
CONVERT(...) SELECT/GROUPBY/ORDERBY
當看到這種程式碼,其實是在暗示資料轉換、資料彙總,都被寫在同一個層級裡了!
❌ 月報的反流程寫法
「我想知道『今年』每一個月實際收到多少訂單金額,用來做營運分析與決策。」
GROUP BY CONVERT(CHAR(7), TradesOrderGroup_DateTime, 120)與 ORDER BY CONVERT(CHAR(7), TradesOrderGroup_DateTime, 120) 都會讓 SQL Server 對每筆資料進行字串轉換
CONVERT() 出現在 SELECT、GROUP BY ORDER BY,SQL Server 會視為三次運算,CPU 多做了三倍的事
1 2 3 4 5 6 7 8 9 10
USE WebStoreDB;
SELECT CONVERT(CHAR(7), TradesOrderGroup_DateTime, 120) AS 月份, SUM(TradesOrderGroup_TotalPayment) AS 總金額 FROM TradesOrderGroup(NOLOCK) WHERE TradesOrderGroup_DateTime >= DATEFROMPARTS(YEAR(GETDATE()), 1, 1) AND TradesOrderGroup_DateTime < DATEFROMPARTS(YEAR(GETDATE()) +1, 1, 1) GROUPBYCONVERT(CHAR(7), TradesOrderGroup_DateTime, 120) ORDERBYCONVERT(CHAR(7), TradesOrderGroup_DateTime, 120);
-- 避免 where 無法吃到索引 DROPTABLE IF EXISTS #yyyyy; select TradesOrderGroup_Id, TradesOrderGroup_DateTime, TradesOrderGroup_TotalPayment into #yyyyy from TradesOrderGroup(nolock) where TradesOrderGroup_DateTime >= DATEFROMPARTS(YEAR(GETDATE()),1, 1) AND TradesOrderGroup_DateTime < DATEFROMPARTS(YEAR(GETDATE()) +1, 1, 1);
-- 避免重複 convert 運算 WITH AA AS( SELECTconvert(char(7),TradesOrderGroup_DateTime, 120) AS MON, TradesOrderGroup_TotalPayment FROM #yyyyy ) select MON,SUM(TradesOrderGroup_TotalPayment) AS Payment from AA GROUPBY MON
SELECT OrderSlaveFlow_Id, OrderSlaveFlow_CreatedDateTime, OrderSlaveFlow_ShippingOrderSlaveDateTime INTO #FlowTemp FROM OrderSlaveFlow (NOLOCK) WHERE OrderSlaveFlow_CreatedDateTime >= DATEFROMPARTS(YEAR(GETDATE()), 1, 1) AND OrderSlaveFlow_CreatedDateTime < DATEFROMPARTS(YEAR(GETDATE()) +1, 1, 1);
WITH CTE AS ( SELECT YEAR(OrderSlaveFlow_CreatedDateTime) AS Y, MONTH(OrderSlaveFlow_CreatedDateTime) AS MON, DATEDIFF(DAY, OrderSlaveFlow_CreatedDateTime, OrderSlaveFlow_ShippingOrderSlaveDateTime) AS timespentforShipping FROM #FlowTemp ) SELECT Y, MON, AVG(timespentforShipping) AS 平均出貨時間 FROM CTE GROUPBY Y, MON;