SQL 内联视图的语法帮助

Syntax assistance for SQL inline view

我仍在学习 SQL 并且正在努力处理内联视图。我一直在做一个项目,在这个项目中我需要考虑某些事情的滞后,因此需要依赖嵌套的东西。但是我对内联视图的语法还不是很好,它一直在括号、逗号等上抛出错误。有人可以帮我清理它以便它运行吗?

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

编辑:我重新格式化了代码并修复了一些标注。事情仍然无法正常工作,但给出的唯一错误是我猜子查询别名,如果那是他们所说的?。对于 )a 和 )c 我有语法错误,并且 )b 说 SiteName 被指定了多次,尽管我只能找到一个。我不确定如何解决该问题。再次,对于所有混乱的代码,我感到很抱歉,我真的很新鲜。

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

我必须从改进缩进开始。这使得更容易查看事情是如何排列的:

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

请注意,我不太在意 SELECT 区域中的项目看起来是否漂亮,而是确保每个嵌套级别的缩进正确。完成后,这部分突然出现在我面前:

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

您似乎在这里遗漏了一些 JOIN。不幸的是,我不能只为你解决这个问题,因为我们无法知道你是否想要 INNER JOIN、LEFT JOIN、CROSS JOIN 等。它还怀疑这个查询在 [=14] 中有一个 * =] 子句。

我注意到的另一件事是下一层的聚合函数。您不能使用 SUM() 之类的聚合函数,除非它们是 SELECT 子句中的唯一字段,您有 GROUP BY 子句,或者它们位于带有 PARTITION BY 的窗口函数(OVER 表达式)中部分。

最后,为了帮助以后更容易管理,我建议将每个级别都写成 CTE(通用 Table 表达式)。这将减少缩进,并且(以我的经验)使查询更容易在心理上进行推理。无需重写 所有内容,这里有一个简短的概述:

WITH LaggedSiteLifetime AS (
    SELECT * , SiteName
            , LAG(....)
    FROM Record...
), PumpCounts AS (
    SELECT *, SiteName, COUNT(.....)
    FROM LaggedSiteLifetime
)
SELECT SiteName, 
      ROUND(...)
FROM PumpCounts

这是我的偏好。有些人更喜欢您已有的嵌套视图,因为它允许他们只突出显示一个部分并在 Management Studio 中按 F5 到 运行 该部分,这会使 运行 变得更难,比如说,只是PumpCounts 部分。但是,我发现这有助于减少嵌套并使缩进更加一致(所有 SELECT/FROM/WHERE/etc 可以处于同一级别)。最重要的是,这让我们可以按照您需要阅读的顺序编写查询以便能够理解它,而另一种方式您必须从内到外阅读内容。