John Ohara
John Ohara

Reputation: 2901

SQL query not returning correct date range

I have a simple view created in VS 2017. Here it is:

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)

As you can see, it gets data between 2 dates and does some simple aggregation.

The idea of the cast is that I want to ignore the time and get everything for the date range regardless - so as of today, 15th Mar, I would it to fetch everything for 14th March 00:00:00 - 23:59:59 and 29 days previous.

This does not happen - it picks up 3 rows (13th) - it should pick up all 5 rows. And yes, my system date is currently 15/03/2018 14:44 (UK time).

Here's, the table and data:

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'[email protected]', 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'[email protected]', 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'[email protected]', 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'[email protected]', 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'[email protected]', 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')

Upvotes: 2

Views: 468

Answers (3)

Grantly
Grantly

Reputation: 2556

You can CAST your CreatedOn field as DATE to remove the time portion, which is getting in your way here...

Perhaps

WHERE CAST(CreatedOn AS DATE) BETWEEN CAST(GETDATE()-30 AS date) AND CAST(GETDATE()-1 AS date)

BUT - CASTing a field in the WHERE expression may make it non SARGable. See here. So avoid this solution for large or production environments unless you know the expression will be SARGable. Use only as a test to refine your logic and options. (Even if there is no explicit index on CreatedOn - it may still suffer as SQL builds its own indexes all the time if no index exists explicitly. Always worth confirming whether it is SARGable so you know for sure.)

To see what is happening - view your values in your SELECT - just to get an idea of what is working

For example:

SELECT TOP 1000
CreatedOn 
,CAST(GETDATE()-30 AS date)
,CAST(GETDATE()-1 AS date)
FROM [Application]

Or see the other options for removing time values from datatime fields here as you may want to coerce or round the time value instead

Upvotes: 3

Tom H
Tom H

Reputation: 47464

Instead of trying to ignore the time value, just make sure that your search terms are accurate for it. Also, don't blindly add things like ISNULL to every column. Spend a few seconds thinking if it's relevant or not. NEWID() for example, is never going to return a NULL value to you. Adding that kind of code is poor programming which will lead to less legible code.

Here's how I would write it to account for the time portions:

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)

Upvotes: 2

EzLo
EzLo

Reputation: 14189

Try this out:

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

The problem is your converting to date the day before today.

Upvotes: 4

Related Questions