按天sql查询不返回与同一范围内的日期范围sql查询相同的结果

按天sql查询不返回与同一范围内的日期范围sql查询相同的结果,sql,sql-server,Sql,Sql Server,我正在编写一些sql来创建报告。为了报告的目的,我需要按天获得结果,而不是整个日期范围内的结果。然而,对于许多数据样本,我实际得到的结果略有不同(按日结果总是较大的值)。也许有人可以解释我遗漏的一个边缘案例或类似的案例。据我所知,这两个查询涵盖的时间段完全相同 白天: DECLARE @VarDate Datetime; SET @VarDate = '2018-07-01'; WHILE @VarDate <= '2018-07-05' BEGIN IF E

我正在编写一些sql来创建报告。为了报告的目的,我需要按天获得结果,而不是整个日期范围内的结果。然而,对于许多数据样本,我实际得到的结果略有不同(按日结果总是较大的值)。也许有人可以解释我遗漏的一个边缘案例或类似的案例。据我所知,这两个查询涵盖的时间段完全相同

白天:

DECLARE @VarDate Datetime;
   SET @VarDate = '2018-07-01';
   WHILE @VarDate <= '2018-07-05'
   BEGIN
      IF EXISTS(SELECT CName, OrderNum, ODescription,
    PDescription, SUM(Qty) as TotalQty, Count(Qty) as Loads
    FROM TICKET
    WHERE TicketDate BETWEEN @VarDate + '00:00:00.00'
    AND @VarDate + '23:59:59.999' GROUP BY CName, OrderNum, ODescription, PDescription)
        SELECT CName, OrderNum, ODescription,
    PDescription, SUM(Qty) as TotalQty, Count(Qty) as Loads
    FROM TICKET
    WHERE TicketDate BETWEEN @VarDate + '00:00:00.00'
    AND @VarDate + '23:59:59.999' GROUP BY CName, OrderNum, ODescription, PDescription
   ELSE
      SELECT @VarDate as Date;
      SET @VarDate = DATEADD(DAY, 1, @VarDate);
   END

编辑:我实际上需要对报告中的不同选项使用这两种方法。澄清一下,我的问题的关键是,是否有人能告诉我,为什么这两个查询会对以总计方式返回的不同行数返回不同的“加载”总计?

如果您需要日期范围之间的每日结果,则不需要执行此操作。另外,您将如何提交此报告

据我所知,我已经创建了一个示例:

DECLARE @DateFrom   DATETIME='2018-07-01';
DECLARE @DateTo     DATETIME='2018-07-05';

SELECT    CName
        , OrderNum
        , ODescription
        , PDescription
        , CAST(TicketDate AS DATE)
        , SUM(Qty) as TotalQty
        , Count(Qty) as Loads
FROM TICKET
WHERE CAST(TicketDate AS DATE) BETWEEN @DateFrom and @DateTo
GROUP BY  CName
        , OrderNum
        , ODescription
        , PDescription
        , CAST(TicketDate AS DATE);

我不能重复这个问题,但是,如果您的目标是在每个日期都有一行,那么可能的答案是这里的最后一个示例。所有3种方法都给出了不同的结果。第一个(a
WHILE
)给出每天的数据集;可能离理想还很远。
WHILE
也是(在许多人看来)这里最糟糕的解决方案,因为它是专门为基于数据集的任务(不是迭代任务)设计的产品上的迭代任务。第二种方法是使用
BETWEEN
生成一个数据集,但只针对表中显示的天数。最后一行为日期范围内的每个日期提供一行,即使它们不在表中

CREATE TABLE dbo.SomeTable (ID int IDENTITY(1,1),
                            SomeDate date,
                            SomeNumber int);
INSERT INTO dbo.SomeTable (SomeDate,SomeNumber)
VALUES ('20181201',12),
       ('20181201',10),
       ('20181203',9),
       ('20181204',8),
       ('20181205',1),
       ('20181205',19);

GO

--Cursor
DECLARE @StartDate date, @EndDate date, @CurrDate date;
SET @StartDate = '20181201';
SET @EndDate = '20181205';
SET @CurrDate = @StartDate;

WHILE @CurrDate <= @EndDate BEGIN
    SELECT SomeDate,
           SUM(SomeNumber) AS TotalSomeNumber
    FROM dbo.SomeTable
    WHERE SomeDate = @CurrDate
    GROUP BY SomeDate;

    SET @CurrDate = DATEADD(DAY, 1, @CurrDate);
END

GO

--BETWEEN

DECLARE @StartDate date, @EndDate date;
SET @StartDate = '20181201';
SET @EndDate = '20181205';

SELECT SomeDate,
        SUM(SomeNumber) AS TotalSomeNumber
FROM dbo.SomeTable
WHERE SomeDate BETWEEN @StartDate AND @EndDate
GROUP BY SomeDate;

GO
--Calendar Table
DECLARE @StartDate date, @EndDate date;
SET @StartDate = '20181201';
SET @EndDate = '20181205';

WITH N AS(
    SELECT N
    FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL)) N(N)),
Tally AS(
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL))-1 AS I
    FROM N),
Dates AS(
    SELECT DATEADD(DAY, I, @StartDate) AS [Date]
    FROM Tally
    WHERE DATEADD(DAY, I, @StartDate) <= @EndDate)
SELECT D.[Date] AS SomeDate,
       ISNULL(SUM(SomeNumber),0) AS TotalSomeNumber
FROM Dates D
     LEFT JOIN dbo.SomeTable ST ON D.[Date] = ST.SomeDate
GROUP BY D.[Date];


GO
DROP TABLE dbo.SomeTable;
创建表dbo.SomeTable(ID int IDENTITY(1,1),
某天,
一些数字(整数);
插入dbo.SomeTable(SomeDate,SomeNumber)
价值('20181201',12),
('20181201',10),
('20181203',9),
('20181204',8),
('20181205',1),
('20181205',19);
去
--光标
声明@StartDate日期、@EndDate日期、@CurrDate日期;
SET@StartDate='20181201';
设置@EndDate='20181205';
设置@CurrDate=@StartDate;

而@CurrDate实际问题是SQL Server将“23:59:59.999”四舍五入,从而将“00:00:00.000”计算了两次,这就是将这些值计算两次的原因,因此计算出了更大的值。我不知道为什么SQL会把这个数字四舍五入,但我希望这对某些人有所帮助

出于兴趣,您为什么在执行此操作时使用
?你真的每天都需要不同的数据集吗?是的。我需要为我正在制作的报告提供每日总计的细分,而while循环是我能够找到的最好的方法,可以在一个记录集中完成这项工作并获得所有结果。但是,如果没有一些样本数据和预期结果,我们将不可能进行复制;一天一个。如果您想要一个数据集,为什么不使用日历表呢?而且,我看不到当数据存在时,您会增加
@VarDate
的值?
CREATE TABLE dbo.SomeTable (ID int IDENTITY(1,1),
                            SomeDate date,
                            SomeNumber int);
INSERT INTO dbo.SomeTable (SomeDate,SomeNumber)
VALUES ('20181201',12),
       ('20181201',10),
       ('20181203',9),
       ('20181204',8),
       ('20181205',1),
       ('20181205',19);

GO

--Cursor
DECLARE @StartDate date, @EndDate date, @CurrDate date;
SET @StartDate = '20181201';
SET @EndDate = '20181205';
SET @CurrDate = @StartDate;

WHILE @CurrDate <= @EndDate BEGIN
    SELECT SomeDate,
           SUM(SomeNumber) AS TotalSomeNumber
    FROM dbo.SomeTable
    WHERE SomeDate = @CurrDate
    GROUP BY SomeDate;

    SET @CurrDate = DATEADD(DAY, 1, @CurrDate);
END

GO

--BETWEEN

DECLARE @StartDate date, @EndDate date;
SET @StartDate = '20181201';
SET @EndDate = '20181205';

SELECT SomeDate,
        SUM(SomeNumber) AS TotalSomeNumber
FROM dbo.SomeTable
WHERE SomeDate BETWEEN @StartDate AND @EndDate
GROUP BY SomeDate;

GO
--Calendar Table
DECLARE @StartDate date, @EndDate date;
SET @StartDate = '20181201';
SET @EndDate = '20181205';

WITH N AS(
    SELECT N
    FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL)) N(N)),
Tally AS(
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL))-1 AS I
    FROM N),
Dates AS(
    SELECT DATEADD(DAY, I, @StartDate) AS [Date]
    FROM Tally
    WHERE DATEADD(DAY, I, @StartDate) <= @EndDate)
SELECT D.[Date] AS SomeDate,
       ISNULL(SUM(SomeNumber),0) AS TotalSomeNumber
FROM Dates D
     LEFT JOIN dbo.SomeTable ST ON D.[Date] = ST.SomeDate
GROUP BY D.[Date];


GO
DROP TABLE dbo.SomeTable;