SQL查询未返回正确的日期范围

时间:2018-03-15 14:50:05

标签: sql sql-server sql-server-2014

我在VS 2017中创建了一个简单的视图。这是:

CREATE VIEW [dbo].[ApplicantStat]
    AS SELECT ISNULL(CONVERT(VARCHAR(50), NEWID()), '') AS ID,
    ISNULL(AVG(ApplicationTime), 0) AS 'AvgApplicationTime',
    ISNULL(AVG(ResponseTime), 0) AS 'AvgResponseTime',
    ISNULL(CAST(COUNT(CASE WHEN [IsAccepted] = 1 THEN 1 END) / COUNT(CASE WHEN [IsValid] = 1 THEN 1 END) AS float), 0) AS 'PctAccepted'
    FROM [Application]
    WHERE CreatedOn BETWEEN CAST(GETDATE()-30 AS date) AND CAST(GETDATE()-1 AS date)

如您所见,它获取2个日期之间的数据并进行一些简单的聚合。

演员的想法是我想忽略时间并且无论如何都要获得日期范围的所有内容 - 所以截至今天,3月15日,我会在3月14日00:00:00 - 23之间取出所有内容: 59:59和29天前。

这不会发生 - 它会拾取3行(第13行) - 它应该拾取所有5行。是的,我的系统日期目前是15/03/2018 14:44(英国时间)。

这是表格和数据:

CREATE TABLE [dbo].[Application] (
    [Id]              INT            NOT NULL,
    [ApplicantId]     INT            NOT NULL,
    [LoanAmount]      INT            NOT NULL,
    [LoanTerm]        SMALLINT       NOT NULL,
    [EmailAddress]    VARCHAR (254)  NOT NULL,
    [MobilePhone]     VARCHAR (11)   NOT NULL,
    [House]           VARCHAR (25)   NOT NULL,
    [Street]          VARCHAR (50)   NOT NULL,
    [TownCity]        VARCHAR (50)   NOT NULL,
    [Postcode]        VARCHAR (7)    NOT NULL,
    [IpAddress]       VARCHAR (39)   NOT NULL,
    [IsValid]         BIT            NOT NULL,
    [IsAccepted]      BIT            NOT NULL,
    [Commission]      DECIMAL (9, 2) NOT NULL,
    [Processors]      VARCHAR (500)  NOT NULL,
    [ResponseTime]    SMALLINT       NOT NULL,
    [ApplicationTime] SMALLINT       NOT NULL,
    [CreatedOn]       DATETIME       NOT NULL,
    PRIMARY KEY CLUSTERED ([Id] ASC)
);

INSERT INTO [dbo].[Application] ([Id], [ApplicantId], [LoanAmount], [LoanTerm], [EmailAddress], [MobilePhone], [House], [Street], [TownCity], [Postcode], [IpAddress], [IsValid], [IsAccepted], [Commission], [Processors], [ResponseTime], [ApplicationTime], [CreatedOn]) VALUES (1, 1, 300, 3, N'john.doe@tmail.com', N'07957000000', N'1', N'Acacia Avenue', N'Suburbia', N'SB1 2RB', N'100.100.100.100', 1, 1, CAST(3.20 AS Decimal(9, 2)), N'1,2,3,4,5', 90, 600, N'2018-03-13 08:00:00')
INSERT INTO [dbo].[Application] ([Id], [ApplicantId], [LoanAmount], [LoanTerm], [EmailAddress], [MobilePhone], [House], [Street], [TownCity], [Postcode], [IpAddress], [IsValid], [IsAccepted], [Commission], [Processors], [ResponseTime], [ApplicationTime], [CreatedOn]) VALUES (2, 2, 500, 12, N'a@b.com', N'0', N'1', N'a', N's', N's', N'1', 0, 1, CAST(5.00 AS Decimal(9, 2)), N'1', 60, 300, N'2018-03-14 16:00:00')
INSERT INTO [dbo].[Application] ([Id], [ApplicantId], [LoanAmount], [LoanTerm], [EmailAddress], [MobilePhone], [House], [Street], [TownCity], [Postcode], [IpAddress], [IsValid], [IsAccepted], [Commission], [Processors], [ResponseTime], [ApplicationTime], [CreatedOn]) VALUES (3, 3, 1000, 6, N'a@b.com', N'0', N'1', N'a', N's', N's', N'1', 1, 1, CAST(7.00 AS Decimal(9, 2)), N'1', 75, 360, N'2018-03-13 10:00:00')
INSERT INTO [dbo].[Application] ([Id], [ApplicantId], [LoanAmount], [LoanTerm], [EmailAddress], [MobilePhone], [House], [Street], [TownCity], [Postcode], [IpAddress], [IsValid], [IsAccepted], [Commission], [Processors], [ResponseTime], [ApplicationTime], [CreatedOn]) VALUES (4, 4, 2000, 24, N'a@b.com', N'0', N'1', N'a', N's', N's', N'1', 1, 1, CAST(20.00 AS Decimal(9, 2)), N'1', 30, 365, N'2018-03-14 11:00:00')
INSERT INTO [dbo].[Application] ([Id], [ApplicantId], [LoanAmount], [LoanTerm], [EmailAddress], [MobilePhone], [House], [Street], [TownCity], [Postcode], [IpAddress], [IsValid], [IsAccepted], [Commission], [Processors], [ResponseTime], [ApplicationTime], [CreatedOn]) VALUES (5, 5, 3000, 18, N'a@b.com', N'0', N'1', N'a', N's', N's', N'1', 1, 1, CAST(40.00 AS Decimal(9, 2)), N'1', 45, 330, N'2018-03-13 12:00:00')

3 个答案:

答案 0 :(得分:4)

试试这个:

WHERE 
    CreatedOn >= CAST(GETDATE()-30 AS date) AND 
    CreatedOn < CAST(GETDATE() AS date)

问题是你在前一天转换为日期。

答案 1 :(得分:3)

您可以CASTCreatedOn字段DATE移除WHERE CAST(CreatedOn AS DATE) BETWEEN CAST(GETDATE()-30 AS date) AND CAST(GETDATE()-1 AS date) 以删除时间部分,这会妨碍您...

也许

CAST

但是 - SELECT TOP 1000 CreatedOn ,CAST(GETDATE()-30 AS date) ,CAST(GETDATE()-1 AS date) FROM [Application] WHERE表达式中的字段可能使其不是SARGable。见here。因此,除非您知道表达式是SARGable,否则请避免在大型或生产环境中使用此解决方案。仅用作测试来优化您的逻辑和选项。 (即使CreatedOn上没有显式索引 - 如果没有明确存在索引,SQL 可能仍然会受到影响,因为SQL会一直构建自己的索引。  总是值得确认它是否是SARGable所以你肯定知道。)

要查看正在发生的事情 - 在SELECT中查看您的值 - 只是为了了解正在运行的内容

例如:

routes.MapRoute("Upload", "Upload/{id}",new { controller = "Upload", action = "Index" });

或查看从数据时间字段here中删除时间值的其他选项 因为你可能想要强制或舍入时间值

答案 2 :(得分:2)

不要试图忽略时间值,只需确保您的搜索字词准确无误。另外,不要盲目地向每列添加ISNULL之类的内容。花几秒钟思考它是否相关。例如,NEWID()永远不会向您返回NULL值。添加这种代码是糟糕的编程,这将导致不太清晰的代码。

以下是我如何编写它来计算时间部分:

CREATE VIEW dbo.ApplicantStat
AS
SELECT
    CONVERT(VARCHAR(50), NEWID()) AS ID,
    COALESCE(AVG(ApplicationTime), 0) AS AvgApplicationTime,
    COALESCE(AVG(ResponseTime), 0) AS AvgResponseTime,
    COALESCE(CAST(COUNT(CASE WHEN [IsAccepted] = 1 THEN 1 END) / COUNT(CASE WHEN [IsValid] = 1 THEN 1 END) AS float), 0) AS PctAccepted
FROM
    dbo.Application
WHERE
    CreatedOn >= DATEADD(DAY, -30, CAST(GETDATE() AS DATE)) AND
    CreatedOn <  CAST(GETDATE() AS DATE)