简体   繁体   中英

SQL Is there a way to use variables in a 'WITH' statement?

I have this 'WITH' statement that pulls out data for each day of the week. The code works but it becomes tedious to change when I modify a variable because I have to go through each and every code block. A lot of the code is repeated. I would like to know if there is a way to place the repeated code into a variable and just repeat the variable?

Edit: Thank you so much for the answer! I did not expect to get one.

WITH 
  cteMonday (CTEdate, CTEtime, DayAverage) AS
  (
select CONVERT(VARCHAR(10), [Datetime], 120) AS Date --extract only the time portion
            ,CONVERT(VARCHAR(5), [Datetime], 108) AS Time  --Extract only the date portion
            ,[High] - [Low] AS hilow 
         from [Trading].[dbo].MicroES
        where DATEPART(dw, Datetime) = 2
        AND CONVERT(VARCHAR(5), [Datetime], 108) = '14:00'
        --AND [Date] >= '2016-07-27'
  ),
    cteTuesday (CTEdate, CTEtime,DayAverage) AS
  (
select CONVERT(VARCHAR(10), [Datetime], 120) AS Date
            ,CONVERT(VARCHAR(5), [Datetime], 108) AS Time --extract only the time portion
            ,[High] - [Low] AS hilow --Extract only the date portion
         from [Trading].[dbo].MicroES
where DATEPART(dw, Datetime) = 3
--AND [Date] >= '2018-07-27'
--AND [Date] >= '2016-07-27'
  ),
      cteWednesday (CTEdate, CTEtime, DayAverage) AS
  (
select CONVERT(VARCHAR(10), [Datetime], 120) AS Date
            ,CONVERT(VARCHAR(5), [Datetime], 108) --extract only the time portion
            ,[High] - [Low] AS hilow --Extract only the date portion
         from [Trading].[dbo].MicroES
where DATEPART(dw, Datetime) = 4
--AND [Date] >= '2018-07-27'
--AND [Date] >= '2016-07-27'
  ),
      cteThursday (CTEdate, CTEtime, DayAverage) AS
  (
select CONVERT(VARCHAR(10), [Datetime], 120) AS Date
            ,CONVERT(VARCHAR(5), [Datetime], 108) AS Time --extract only the time portion
            ,[High] - [Low] AS hilow --Extract only the date portion
         from [Trading].[dbo].MicroES
where DATEPART(dw, Datetime) = 5
--AND [Date] >= '2018-07-27'
--AND [Date] >= '2016-07-27'
  ),
      cteFriday (CTEdate, CTEtime, DayAverage) AS
  (
select CONVERT(VARCHAR(10), [Datetime], 120) AS Date
            ,CONVERT(VARCHAR(5), [Datetime], 108) AS Time --extract only the time portion
            ,[High] - [Low] AS hilow --Extract only the date portion
         from [Trading].[dbo].MicroES
where DATEPART(dw, Datetime) = 6
AND CONVERT(VARCHAR(5), [Datetime], 108) = '14:00'
--AND [Date] >= '2016-07-27'
  )

  select 
  'Monday' AS 'Day',
AVG(DayAverage) AS 'DayAverage',
    MIN(DayAverage) as min_day,
  MAX(DayAverage) as max_day,
  COUNT(DayAverage) as 'Days'  
   from cteMonday

   UNION ALL 
     select 
  'Tuesday' AS 'Day',
  AVG(DayAverage) AS DayAverage,
    MIN(DayAverage) as min_day,
  MAX(DayAverage) as max_day,
  COUNT(DayAverage) as 'Days'  
   from cteTuesday

   UNION ALL
     select 
  'Wednesday' AS 'Day',
  AVG(DayAverage) AS 'DayAverage',
    MIN(DayAverage) as min_day,
  MAX(DayAverage) as max_day,
  COUNT(DayAverage) as 'Days'  
   from cteWednesday

      UNION ALL
     select 
  'Thursday' AS 'Day',
  AVG(DayAverage) AS 'DayAverage',
    MIN(DayAverage) as min_day,
  MAX(DayAverage) as max_day,
  COUNT(DayAverage) as 'Days'  
   from cteThursday

      UNION ALL
     select 
  'Friday' AS 'Day',
  AVG(DayAverage) AS 'DayAverage',
    MIN(DayAverage) as min_day,
  MAX(DayAverage) as max_day,
  COUNT(DayAverage) as 'Days'  
   from cteFriday

This is too long for a comment, but couldn't you rewrite the entire statement as below?

USE Trading;
GO

SELECT DATENAME(WEEKDAY, M.[DateTime]),
       AVG(M.[High] - M.[Low]) AS DayAverage,
       MIN(M.[High] - M.[Low]) as min_day,
       MAX(M.[High] - M.[Low]) as max_day,
       COUNT(M.[High] - M.[Low]) as Days  
FROM dbo.MicroES M
WHERE (DATEPART(weekday,M.[Datetime]) IN (3,4,5)
   OR (DATEPART(weekday,M.[Datetime]) IN (2,6) AND CONVERT(time, M.[DateTime]) = '14:00')) --Courtesy of LukStorm's correction
GROUP BY DATENAME(WEEKDAY, M.[DateTime]);

This will still perform poorly, due to the functions on [Datetime] in the WHERE , and I created computed columns for them. but it'll certainly be better than 5 scans of your table MicroES with the same non-SARGable clauses.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM