Reputation: 61
I'm still learning SQL and struggling with inline views. I have been working on a project where I need to account for lags with certain things and so need to rely on having things nested so to speak. But I am not great with the syntax on inline views yet and it keeps throwing errors on parentheses, commas, etc. Could someone help me clean it up so it runs?
SELECT *
, SiteName
, VentCount AS 'Number Of Vents'
, ROUND(PumpAHours,1) AS 'Pump A Hours'
, ROUND(PumpBHours,1) AS 'Pump B Hours'
, ROUND(PumpAStarts, 1) AS 'Pump A Starts'
, ROUND(PumpBStarts, 1) AS 'Pump B Starts'
FROM (
SELECT * , SiteName
, SUM(CASE WHEN ECV36_Open_Count_Lifetime - Lag_ECV36_Open_Count_Lifetime Between 1 AND 5 THEN ECV36_Open_Count_Lifetime - Lag_ECV36_Open_Count_Lifetime ELSE 0 END) AS 'VentCount'
, CASE WHEN NULLIF(SUM(CASE WHEN PumpAStatus LIKE '%Running%' THEN 1 ELSE 0 END) / CAST(20 AS FLOAT),0) < MAX(Pump_A_Hours) - MIN(Pump_A_Hours)
THEN SUM(CASE WHEN PumpAStatus LIKE '%Running%' THEN 1 ELSE 0 END) / CAST(20 AS FLOAT)
ELSE MAX(Pump_A_Hours) - MIN(Pump_A_Hours) END AS 'PumpAHours'
, CASE WHEN NULLIF(SUM(CASE WHEN PumpBStatus LIKE '%Running%' THEN 1 ELSE 0 END) / CAST(20 AS FLOAT),0) < MAX(Pump_B_Hours) - MIN(Pump_B_Hours)
THEN SUM(CASE WHEN PumpBStatus LIKE '%Running%' THEN 1 ELSE 0 END) / CAST(20 AS FLOAT)
ELSE MAX(Pump_B_Hours) - MIN(Pump_B_Hours) END AS 'PumpBHours'
,COUNT(CASE WHEN Pump_A_StateId = 12 OR Pump_A_StateId = 14 OR Pump_A_StateId = 9 OR Pump_A_StateId = 1837 OR Pump_A_StateId = 1839 THEN 1 END) AS PumpAStarts
,COUNT(CASE WHEN Pump_B_StateId = 12 OR Pump_B_StateId = 14 OR Pump_B_StateId = 9 OR Pump_B_StateId = 1837 OR Pump_B_StateId = 1839 THEN 1 END) AS PumpBStarts
FROM (
SELECT * , SiteName
, LAG([ECV36_Open_Count_Lifetime],1,NULL) OVER(PARTITION BY R.SiteId ORDER BY RecordDateTime ASC) AS 'Lag_ECV36_Open_Count_Lifetime'
FROM (
[Cryo].[dbo].[Record] R
Cryo.dbo.Site S on S.SiteId = R.RecordId
Cryo.dbo.pad P on P.RecordId = R.RecordId
Cryo.dbo.Pump PP on PP.RecordId = R.RecordId
)a
)a
WHERE RecordDateTime BETWEEN DATEADD(DD,-1,CONVERT(DATE,GETDATE())) AND DATEADD(DD, 0,CONVERT(DATE,GETDATE()))
)a
EDIT: I reformatted the code and fixed some of the callouts. Things still aren't working but the only errors being given is with the I guess subquery aliases if that's what they are called?. For )a and )c I have syntax errors and )b says SiteName was specified multiple times, though I can just find one. I'm not sure how to fix that issue. Again, sorry for all the messy code, I'm really fresh.
SELECT * ,
sitename ,
ventcount AS 'Number Of Vents' ,
Round(pumpahours,1) AS 'Pump A Hours' ,
Round(pumpbhours,1) AS 'Pump B Hours' ,
Round(pumpastarts, 1) AS 'Pump A Starts' ,
Round(pumpbstarts, 1) AS 'Pump B Starts'
FROM (
SELECT * ,
sitename ,
Sum(
CASE
WHEN ecv36_open_count_lifetime - lag_ecv36_open_count_lifetime BETWEEN 1 AND 5 THEN ecv36_open_count_lifetime - lag_ecv36_open_count_lifetime
ELSE 0
END) AS 'VentCount' ,
CASE
WHEN NULLIF(Sum(
CASE
WHEN pumpastatus LIKE '%Running%' THEN 1
ELSE 0
END) / Cast(20 AS FLOAT),0) < Max(pump_a_hours) - Min(pump_a_hours) THEN Sum(
CASE
WHEN pumpastatus LIKE '%Running%' THEN 1
ELSE 0
END) / Cast(20 AS FLOAT)
ELSE Max(pump_a_hours) - Min(pump_a_hours)
END AS 'PumpAHours' ,
CASE
WHEN NULLIF(Sum(
CASE
WHEN pumpbstatus LIKE '%Running%' THEN 1
ELSE 0
END) / Cast(20 AS FLOAT),0) < Max(pump_b_hours) - Min(pump_b_hours) THEN Sum(
CASE
WHEN pumpbstatus LIKE '%Running%' THEN 1
ELSE 0
END) / Cast(20 AS FLOAT)
ELSE Max(pump_b_hours) - Min(pump_b_hours)
END AS 'PumpBHours' ,
Count(
CASE
WHEN pump_a_stateid = 12
OR pump_a_stateid = 14
OR pump_a_stateid = 9
OR pump_a_stateid = 1837
OR pump_a_stateid = 1839 THEN 1
END) AS pumpastarts ,
Count(
CASE
WHEN pump_b_stateid = 12
OR pump_b_stateid = 14
OR pump_b_stateid = 9
OR pump_b_stateid = 1837
OR pump_b_stateid = 1839 THEN 1
END) AS pumpbstarts
FROM (
SELECT * ,
s.SiteName ,
Lag([ECV36_Open_Count_Lifetime],1,NULL) OVER(partition BY r.siteid ORDER BY recorddatetime ASC) AS 'Lag_ECV36_Open_Count_Lifetime'
FROM ( [Cryo].[dbo].[Record] R JOIN cryo.dbo.site s ON s.siteid = r.recordid JOIN cryo.dbo.pad p ON p.recordid = r.recordid JOIN cryo.dbo.pump pp ON pp.recordid = r.recordid )a
WHERE recorddatetime BETWEEN dateadd(dd,-1,CONVERT(date,getdate())) AND dateadd(dd, 0,CONVERT(date,getdate())) )b )c
Upvotes: 1
Views: 143
Reputation: 415830
I had to start by improving indentation. This makes it so much easier to see how things line up:
SELECT *
, SiteName
, VentCount AS 'Number Of Vents'
, ROUND(PumpAHours,1) AS 'Pump A Hours'
, ROUND(PumpBHours,1) AS 'Pump B Hours'
, ROUND(PumpAStarts, 1) AS 'Pump A Starts'
, ROUND(PumpBStarts, 1) AS 'Pump B Starts'
FROM (
SELECT * , SiteName
, SUM(CASE WHEN ECV36_Open_Count_Lifetime - Lag_ECV36_Open_Count_Lifetime Between 1 AND 5 THEN ECV36_Open_Count_Lifetime - Lag_ECV36_Open_Count_Lifetime ELSE 0 END) AS 'VentCount'
, CASE WHEN NULLIF(SUM(CASE WHEN PumpAStatus LIKE '%Running%' THEN 1 ELSE 0 END) / CAST(20 AS FLOAT),0) < MAX(Pump_A_Hours) - MIN(Pump_A_Hours)
THEN SUM(CASE WHEN PumpAStatus LIKE '%Running%' THEN 1 ELSE 0 END) / CAST(20 AS FLOAT)
ELSE MAX(Pump_A_Hours) - MIN(Pump_A_Hours) END AS 'PumpAHours'
, CASE WHEN NULLIF(SUM(CASE WHEN PumpBStatus LIKE '%Running%' THEN 1 ELSE 0 END) / CAST(20 AS FLOAT),0) < MAX(Pump_B_Hours) - MIN(Pump_B_Hours)
THEN SUM(CASE WHEN PumpBStatus LIKE '%Running%' THEN 1 ELSE 0 END) / CAST(20 AS FLOAT)
ELSE MAX(Pump_B_Hours) - MIN(Pump_B_Hours) END AS 'PumpBHours'
,COUNT(CASE WHEN Pump_A_StateId = 12 OR Pump_A_StateId = 14 OR Pump_A_StateId = 9 OR Pump_A_StateId = 1837 OR Pump_A_StateId = 1839 THEN 1 END) AS PumpAStarts
,COUNT(CASE WHEN Pump_B_StateId = 12 OR Pump_B_StateId = 14 OR Pump_B_StateId = 9 OR Pump_B_StateId = 1837 OR Pump_B_StateId = 1839 THEN 1 END) AS PumpBStarts
FROM (
SELECT * , SiteName
, LAG([ECV36_Open_Count_Lifetime],1,NULL) OVER(PARTITION BY R.SiteId ORDER BY RecordDateTime ASC) AS 'Lag_ECV36_Open_Count_Lifetime'
FROM (
[Cryo].[dbo].[Record] R
Cryo.dbo.Site S on S.SiteId = R.RecordId
Cryo.dbo.Pad P on P.RecordId = R.RecordId
Cryo.dbo.Pump PP on PP.RecordId = R.RecordId
)a
)a
WHERE RecordDateTime BETWEEN DATEADD(DD,-1,CONVERT(DATE,GETDATE())) AND DATEADD(DD, 0,CONVERT(DATE,GETDATE()))
)a
Notice I didn't care as much about making items in the SELECT area look pretty as I did making sure the indentation of each level of nesting was correct. With that done, this section jumps out at me:
FROM (
[Cryo].[dbo].[Record] R
Cryo.dbo.Site S on S.SiteId = R.RecordId
Cryo.dbo.Pad P on P.RecordId = R.RecordId
Cryo.dbo.Pump PP on PP.RecordId = R.RecordId
It looks like you're missing some JOINs here. Unfortunately, I can't just fix that for you, because we have no way to know whether you want INNER JOIN, LEFT JOIN, CROSS JOIN, etc. It's also suspect this query has a *
in the SELECT
clause.
Another thing I noticed is the aggregate functions in the next level up. You can't use aggregate functions like SUM()
unless they are the only field in the SELECT clause, you have a GROUP BY clause, or they are inside a windowing function (OVER expression) with a PARTITION BY section.
Finally, to help make this easier to manage going forward, I suggest writing each level as a CTE (Common Table Expression). That will reduce indenting and (in my experience) makes the query easier to reason about mentally. Without re-writing everything, here's an abbreviated overview of how that would look:
WITH LaggedSiteLifetime AS (
SELECT * , SiteName
, LAG(....)
FROM Record...
), PumpCounts AS (
SELECT *, SiteName, COUNT(.....)
FROM LaggedSiteLifetime
)
SELECT SiteName,
ROUND(...)
FROM PumpCounts
This is my preference. Some people prefer the nested view you already have, because it allows them to highlight just a section and hit F5 in Management Studio to run that section, where this would make it harder to run, say, just the PumpCounts
section. However, I find this helps by reducing nesting and making indentation more consistent (all SELECT/FROM/WHERE/etc can be at the same level). Most of all, this lets us write the query in the order you need to read it to be able to understand it, where the other way you have to kind of read things from the inside out.
Upvotes: 2