【问题标题】:Rewrite into single query重写为单个查询
【发布时间】:2015-11-22 07:27:25
【问题描述】:

我必须将要合并到一个查询中的选择查询分开。这意味着我希望我的输出格式如下:

第 1 列 | col2

252 ---- 05

一个想法是编写一个 CTE,虽然这两个是小查询,但对于日期范围,我还有大约 4 个这样的查询,我认为避免使用一个或多个 CTES 来获取数据。

这是我的选择查询:

SELECT 
  count(*) as pastDueRepl   
FROM TBLPTS_APPDATA 
WHERE APPV_PTSSTATUS = '2'      
  AND (APPD_NEXTREPLDATE IS NOT NULL)   
  AND APPD_NEXTREPLDATE between DATEADD(Day,-30,GETDATE()) and GETDATE()

SELECT 
  count(*) as pastDueInsp   
FROM TBLPTS_APPDATA 
WHERE APPV_PTSSTATUS = '2'      
  AND (APPD_NEXTINSPDATE IS NOT NULL) 
  AND APPD_NEXTINSPDATE between DATEADD(Day,-30,GETDATE()) and GETDATE()    

【问题讨论】:

  • 是拼写错误,还是您真的针对APPD_NEXTINSPDATE 对这两个查询进行了日期范围检查?
  • 打错了,谢谢
  • 请注意,“不为空”的过滤器不是必需的,因为您也在其他地方过滤相同的字段。

标签: sql sql-server-2012 subquery correlated-subquery


【解决方案1】:

这是一个很好的方法,可以最大限度地减少重复并减少硬编码日期范围边界的次数:

  with DateRangeBoundaries as (select DATEADD(Day,-30,GETDATE()) as LowerBoundDate,
                                      GETDATE() as UpperBoundDate)
select count(case when t.APPD_NEXTREPLDATE between drb.LowerBoundDate and drb.UpperBoundDate
                  then 'X' end) as pastDueRepl,
       count(case when t.APPD_NEXTINSPDATE between drb.LowerBoundDate and drb.UpperBoundDate
                  then 'X' end) as pastDueInsp
  from TBLPTS_APPDATA t
  join DateRangeBoundaries drb on 1=1
 where t.APPV_PTSSTATUS = '2'

以上内容可能会为您提供更紧凑的语法。但是,如果您依赖日期列上的索引,那么上述内容实际上可能会损害您的性能。如果您决定尝试,请确保您对此进行了概要分析。

【讨论】:

    【解决方案2】:

    我会使用条件聚合并在聚合函数中使用不同的条件,因此对于匹配条件 1 的每一行,都会将其添加到总和(用作计数):

    SELECT 
        SUM(
           CASE 
            WHEN APPD_NEXTINSPDATE between DATEADD(Day,-30,GETDATE()) and GETDATE() 
              THEN 1 
             ELSE 0 
           END
        ) AS pastDueInsp,
        SUM(
           CASE 
            WHEN APPD_NEXTREPLDATE between DATEADD(Day,-30,GETDATE()) and GETDATE() 
              THEN 1 
            ELSE 0 
           END
        ) AS pastDueRepl   
    FROM TBLPTS_APPDATA 
    WHERE APPV_PTSSTATUS = '2';
    

    或者您可以使用union all 运算符来合并语句,或者将每个语句用作派生表或cte。这么多选择。

    【讨论】:

      【解决方案3】:

      这应该让你开始:

      select case when APPD_NEXTREPLDATE is not null and APPD_NEXTINSPDATE is null then 'a'
      when APPD_NEXTREPLDATE is null and APPD_NEXTINSPDATE is not null then 'b'
      when APPD_NEXTREPLDATE is not null and APPD_NEXTINSPDATE is not null then 'c'
      else 'd' end status
      , count(*) records
      
      from etc
      where etc
      
      group by case when APPD_NEXTREPLDATE is not null and APPD_NEXTINSPDATE is null then 'a'
      when APPD_NEXTREPLDATE is null and APPD_NEXTINSPDATE is not null then 'b'
      when APPD_NEXTREPLDATE is not null and APPD_NEXTINSPDATE is not null then 'c'
      else 'd' end
      

      详细信息取决于您的要求。

      【讨论】:

        【解决方案4】:

        0 列添加到每个查询中,然后将sum 添加到union 上:

        SELECT SUM(pastDueRepl) as pastDueRepl, sum(pastDueInsp) as pastDueInsp  FROM(
          SELECT 
          count(*) as pastDueRepl   , 0 as pastDueInsp  
          FROM TBLPTS_APPDATA 
          WHERE APPV_PTSSTATUS = '2'        
          AND (APPD_NEXTREPLDATE IS NOT NULL)   
          AND APPD_NEXTINSPDATE between DATEADD(Day,-30,GETDATE()) and GETDATE()
        
          UNION ALL
        
          SELECT 
          0 as pastDueRepl, count(*) as pastDueInsp 
          FROM TBLPTS_APPDATA 
          WHERE APPV_PTSSTATUS = '2'        
          AND (APPD_NEXTINSPDATE IS NOT NULL) 
          AND APPD_NEXTINSPDATE between DATEADD(Day,-30,GETDATE()) and GETDATE()    
        ) t
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-07-19
          • 1970-01-01
          • 2021-12-17
          • 1970-01-01
          • 2019-11-08
          • 1970-01-01
          相关资源
          最近更新 更多