按天sql查询不返回与同一范围内的日期范围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
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;