【问题标题】:Loop Through 1 SQL Query, Instead Of Using 2 Queries循环 1 个 SQL 查询,而不是使用 2 个查询
【发布时间】:2017-06-15 17:16:01
【问题描述】:

下面我有一个带有两个基本 SELECT 语句的变量。如果用户只能使用一个变量 @StartDate 来输入日期参数​​,那么如何循环查询以仅使用一个 SELECT 语句而不是如下所示的两个。因此,假设您没有两个查询,而是一个查询,它只能运行一次,但满足下面 WHERE 子句中的两个条件,即“FullDate = @StartDate”和“Fulldate BETWEEN DATEADD(mm, DATEDIFF( mm, 0, @StartDate), 0) 和 @StartDate”。所以,基本上我试图将两个 SELECT 语句压缩为一个,并提供来自两个查询的相关数据。此处不能使用 UNION ALL。

DECLARE @StartDate DATE = '20170610'

SELECT
    FirstName,
    LastName,
    SUM(MoneySpent) AS 'Spent'  
FROM
    TableOne  
WHERE
    FullDate = @StartDate;  
GROUP BY FirstName, LastName

SELECT 
    FirstName,
    LastName,
    SUM(MoneySpent) AS 'Spent'    
FROM
    TableOne    
WHERE
    Fulldate BETWEEN DATEADD(mm, DATEDIFF(mm, 0, @StartDate), 0) AND @StartDate;  
GROUP BY FirstName, LastName

【问题讨论】:

  • 你确定 Fulldate = DATEADD(mm, DATEDIFF(mm, 0, @StartDate), 0) AND @StartDate 是正确的吗?
  • Fulldate = DATEADD(mm, DATEDIFF(mm, 0, @StartDate), 0) AND @StartDate 没有意义。你是说这两者之间? (例如,在@StartDate 和@StartDate 的月初之间?)
  • 关于 BETWEEN 您需要了解的一点是它包含端点,第一个选择中的任何内容都将按原样出现在您的第二个选择中,因此只需删除第一个选择即可。

标签: sql sql-server tsql


【解决方案1】:

如果你有两个日期@Date1 和@Date2,那么你可以使用这个:

SELECT
    FirstName,
    LastName,
    SUM(CASE WHEN FullDate = @Date1 THEN MoneySpent ELSE 0 END) AS 'SpentDate1',
    SUM(CASE WHEN FullDate = @Date2 THEN MoneySpent ELSE 0 END) AS 'SpentDate2'  
FROM
    TableOne  
WHERE
    FullDate = @Date1 OR FullDate = @Date2
GROUP BY FirstName, LastName

顺便说一句,UNION ALL 也可以使用,您只需将其包装为子查询并使用额外的 GROUP BY

【讨论】:

  • 如果只允许使用一个日期参数而不允许使用 UNION ALL 怎么办?
  • 使用上面的查询——它没有联合所有,date1和date2只是占位符,用你自己的条件替换
【解决方案2】:

关于 BETWEEN 您需要了解的一点是它包含端点,因此您只需要第二个查询即可获得您要查找的内容。

SELECT 
    FirstName,
    LastName,
    SUM(MoneySpent) AS 'Spent'    
FROM
    TableOne    
WHERE
    Fulldate BETWEEN DATEADD(mm, DATEDIFF(mm, 0, @StartDate), 0) AND @StartDate;  
GROUP BY FirstName, LastName

【讨论】:

    【解决方案3】:

    我认为第一个查询已经被第二个查询覆盖了。

                SELECT  FirstName ,
                        LastName ,
                        SUM(MoneySpent) AS 'Spent'
                FROM    TableOne
                WHERE   Fulldate BETWEEN DATEADD(mm, DATEDIFF(mm, 0, @StartDate), 0)
                                 AND     @StartDate 
                GROUP BY FirstName, LastName
    

    但是为了争论,许多选项之一是您可以将每个查询的相关数据放入临时表中。

    例如

            DECLARE @StartDate DATE = '2017.06.10';
    
    
            IF ( OBJECT_ID('tempdb..#tempTbl') IS NOT NULL )
                BEGIN
                    DROP TABLE #tempTbl
                END
    
            CREATE TABLE #tempTbl
                (
                  ID INT IDENTITY(1, 1)
                         PRIMARY KEY ,
                  FirstName VARCHAR(100) ,
                  LastName VARCHAR(100) ,
                  Spent MONEY
                )
    
            INSERT  INTO #tempTbl
                    ( FirstName ,
                      LastName ,
                      Spent
                    )
                    SELECT  FirstName ,
                            LastName ,
                            SUM(MoneySpent) AS 'Spent'
                    FROM    TableOne
                    WHERE   FullDate = @StartDate
    
            INSERT  INTO #tempTbl
                    ( FirstName ,
                      LastName ,
                      Spent
                    )
                    SELECT  FirstName ,
                            LastName ,
                            SUM(MoneySpent) AS 'Spent'
                    FROM    TableOne
                    WHERE   Fulldate BETWEEN DATEADD(mm, DATEDIFF(mm, 0, @StartDate), 0)
                                     AND     @StartDate 
    
            SELECT  FirstName,LastName,Spent
            FROM    #tempTbl
            GROUP BY FirstName, LastName
    

    【讨论】:

      【解决方案4】:

      我认为,您注意到一个结果集是另一个结果集的子集。 也就是说,Range Between条件满足相等条件。所以结果不重复。

      例如using AdventureWorks2012

          DECLARE @StartDate DATE = '20020224'
          DECLARE @StartDate1 DATE = '20020303'
      
      select a.BusinessEntityID
      ,a.RateChangeDate,sum(a.rate)  Rate
      from HumanResources.EmployeePayHistory a
      where a.RateChangeDate
       BETWEEN DATEADD(mm, DATEDIFF(mm, 0, @StartDate), 0) AND @StartDate
       or a.RateChangeDate=@StartDate1
       GROUP by a.BusinessEntityID,a.RateChangeDate
      

      这里两个日期的结果都是可见的 (6 rows)

      如果我们做到这一点

      DECLARE @StartDate DATE = '20020224'
      DECLARE @StartDate1 DATE = StartDate
      

      between condtion 到这里满足RateChangeDate=@StartDate1 所以输出只有 5 rows

      所以你的想法是无法实现的。

      如果我遇到同样的问题,我只会使用select ... FullDate between

      在前端我会pull data for fulldate=@StartDate

      如果你真的像现在这样使用 2 Select 然后这样做,

      ;With CTE as
      (
      SELECT 
          FirstName,
          LastName,
          Fulldate,
          SUM(MoneySpent) AS 'Spent'    
      FROM
          TableOne    
      WHERE
          Fulldate BETWEEN DATEADD(mm, DATEDIFF(mm, 0, @StartDate), 0) AND @StartDate;  
      GROUP BY FirstName, LastName,Fulldate
      )
      select *,0 flg from cte
      union ALL
      select * ,1 flg from cte 
      where Fulldate=@StartDate
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-07-26
        • 2013-11-17
        • 1970-01-01
        • 2016-02-01
        • 2013-05-17
        • 2021-10-25
        • 2016-10-16
        相关资源
        最近更新 更多