Adding months in where clause in sql - sql

I am writing a sp for getting the data for the next 6 months for a particular date field,
SELECT CR.[Id] AS ClaimId
,CR.[BOLNumber]
,CR.[PRONumber]
,CR.[ClaimNumber]
,CR.[CompanyName]
,c.NAME AS CarrierName
,CR.[DateFiled]
,CONVERT(VARCHAR(10),CR.[DateFiled], 103) AS DateFiledString
,CR.[ClaimDate] AS ClaimReceivedDate
,CONVERT(VARCHAR(10), CR.[ClaimDate], 103) AS ClaimReceivedDateString
,CR.[AmountFiled]
,CR.[Status] AS StatusId
,CR.[SettledAmount]
FROM CarrierRate.Claims AS CR WITH (NOLOCK)
WHERE CR.CustomerId = #AccountUserId AND
CR.Status = #statusType AND CR.ClaimDate < DATEADD(month,6,CR.ClaimDate)
ORDER BY CR.[Status] ASC
The field is ClaimDate. So am i doing it right or anything to be changed?
Please suggest

You can try
CONVERT(DATE, CR.ClaimDate) < DATEADD(MONTH,6,CONVERT(DATE, CR.ClaimDate))
only date is considered here.

Use BETWEEN keyword to specify date range.
WHERE CR.CustomerId = #AccountUserId AND
CR.Status = #statusType AND
CR.ClaimDate BETWEEN GETDATE() AND DATEADD(month,6,CR.ClaimDate)

(CR.ClaimDate BETWEEN DATEADD(month,-6,GETDATE()) AND GETDATE()
OR #statusType <> 2)

Related

SQL Server Yesterdays Count

I am trying to get a count of all of yesterdays rows. The query i have runs good but does not pick up null values. Is there a way i can query a count of null and non null values?
Here is my code:
SELECT dateadd(day,datediff(day,0,GETDATE())-1,0) as Received_Date,
COUNT(*) as Enrollments_Completed
FROM Table CD,
CCMDB.dbo.ResolutionLetterDetails RD
WHERE CD.ccid = RD.ccid
and CompletedDate >= DATEADD(d,DATEDIFF(d,1,getdate()),0)
and CompletedDate < DATEADD(d,DATEDIFF(d,0,getdate()),0)
AND CatID in('cat0014')
AND IncomingType <> 'RITS'
AND status = 'Completed'
Convert your CompletedDate to a date with no time and make it equal yesterdays date with no time (from GETDATE()) and use correct JOIN code.
SELECT dateadd(day,datediff(day,0,GETDATE())-1,0) as Received_Date,
COUNT(*) as Enrollments_Completed
FROM Table CD
LEFT JOIN CCMDB.dbo.ResolutionLetterDetails RD ON CD.ccid = RD.ccid
WHERE dateadd(day,datediff(day,1,CompletedDate),0) = dateadd(day,datediff(day,1,GETDATE()),0)
AND CatID IN ('cat0014')
AND IncomingType != 'RITS'
AND status = 'Completed'
Return NULLs:
SELECT dateadd(day,datediff(day,0,GETDATE())-1,0) as Received_Date,
COUNT(*) as Enrollments_Completed
FROM Table CD
LEFT JOIN CCMDB.dbo.ResolutionLetterDetails RD ON CD.ccid = RD.ccid
WHERE dateadd(day,datediff(day,1,CompletedDate),0) = dateadd(day,datediff(day,1,GETDATE()),0)
AND (CatID IN ('cat0014') OR CatID IS NULL)
AND (IncomingType != 'RITS' OR IncomingType IS NULL)
AND (status = 'Completed' OR status IS NULL)
I would fix your query and do:
SELECT CAST(DATEADD(day, -1, GETDATE()) as DATE) as Received_Date,
COUNT(*) as Enrollments_Completed
FROM Table CD JOIN
CCMDB.dbo.ResolutionLetterDetails RD
ON CD.ccid = RD.ccid
WHERE CompletedDate >= CAST(DATEADD(day, -1, GETDATE()) as DATE) AND
CompletedDate < CAST(GETDATE() as DATE) AND
CatID IN ('cat0014') AND
IncomingType <> 'RITS' AND
status = 'Completed';
For the date part, you could also do:
CAST(CompletedDate as DATE) = CAST(DATEADD(day, -1, GETDATE()) as DATE)
This version is even index-safe in SQL Server (although not necessarily in other databases).
Notes:
The DATE data type considerably simplifies your calculations.
Never use commas in the FROM clause. Always use proper, explicit, standard JOIN syntax.
You should qualify all column names so you (and anyone reading the query) knows what table the column comes from.

Get the DueDate if the date is today

I am assigned to create an alert that if today is the duedate of an item, then the alert will be sent to the team.
I am trying to check how I can filter the where clause of my code:
SELECT dbo.salesorder.customerid,
dbo.salesorder.entrydate,
dbo.salesorder.salesorderno,
dbo.salesorderdetails.itemno,
dbo.salesorder.usercreated,
dbo.salesorder.duedate
from dbo.salesorder
inner JOIN dbo.salesorderdetails
ON dbo.salesorder.salesorderid = dbo.salesorderdetails.salesorderid
where (dbo.salesorder.customerid = 238)
If today is 4th of May, I just my report to display the below-highlighted sales orders.
convert getdate() to date and compare with the duedate
where (dbo.salesorder.customerid = 238)
and dbo.salesorder.duedate = convert(date, getdate())
SELECT dbo.salesorder.customerid,
dbo.salesorder.entrydate,
dbo.salesorder.salesorderno,
dbo.salesorderdetails.itemno,
dbo.salesorder.usercreated,
dbo.salesorder.duedate
from dbo.salesorder
inner JOIN dbo.salesorderdetails
ON dbo.salesorder.salesorderid = dbo.salesorderdetails.salesorderid
where dbo.salesorder.duedate = CAST(GETDATE() AS DATE) --or CAST(CURRENT_TIMESTAMP AS DATE)
and dbo.salesorder.customerid = 238

Using an Aggregate function with a sub query

We get a new batch of widgets each month. We know the product codes of these widgets which will be is stock, waiting to be used. Each also has an availability date, after which it can be used.
Table WidgetStock
Columns: WidgetID, AvailabilityDate,
Another table has the uses of the widget, ie when it was first used.
Table WidgetsUsed
Columns: datetime, Operator
I'd like to see by day and hour the amount of fresh widgets that I have used for the first time, since the start of the month. The widgets will be used multiple times, so a simple distinct count by hour is not really enough, as widgets would be double counted.
In my mind this would require looking at a list of available numbers, which is updated for each line of a group by query.
The below query will not work, but hopefully it shows what I am trying to achieve:
declare #StartofMonth datetime
set #StartofMonth = '20160901'
select CONVERT(varchar, wu.datetime, 103)'Date'
, convert(char(2), wu.datetime, 108)'Hour'
--Problem Line below
, SUM(case when wu.StockNo in (select ba.NUMBER
from widgetStock ba
where availability_date between CONVERT(varchar, wu.datetime, 103) and #StartofMonth) then 1 else 0 end) 'Number Used'
from widgetsUsed wu
left join widgetStock ws on wu.StockNo = ws.NUMBER
where wu.OPERATOR = 'WidgetWorld'
and DATETIME between '20160914' and '20160916'
group by CONVERT(varchar,wu.datetime,103), convert(char(2), wu.datetime, 108)
Any help with this is appreciated. Thanks in advance.
If understood your requirement then below script may solve your problem
declare #StartofMonth datetime
set #StartofMonth = '20160901'
select CONVERT(varchar, wu.datetime, 103)'Date'
, convert(char(2), wu.datetime, 108)'Hour'
, SUM(ISNULL(ba.NUMBER,0)) 'Number Used'
from widgetsUsed wu
left join widgetStock ws on wu.StockNo = ws.NUMBER
LEFT JOIN widgetStock ba ON wu.StockNo = ba.NUMBER AND availability_date between CONVERT(varchar, wu.datetime, 103) and #StartofMonth
where wu.OPERATOR = 'WidgetWorld'
and DATETIME between '20160914' and '20160916'
group by CONVERT(varchar,wu.datetime,103), convert(char(2), wu.datetime, 108)

SQL Server : WHERE clause case with between

I have a script which I want to extract values from db accordingly with some dates.
I have a function which return a date, this date can be currentDate - 1 month, or can be curentDate -2 months. The function is
set #syssDate = DATEADD(month, -1, #syss_date);
and I have declared a start date:
declare #start_quarter datetime
set #start_quarter = '2015-07-01';
All I want in my WHERE clause to add a
case
when syssDate = start_quarter
then bu.date between '2015-01-01' and '2015-10-01'
else -- another date
My query looks like:
declare #start_quarter datetime
set #start_quarter = '2015-01-01';
declare #actual_Date datetime
set #actual_Date = DATEADD(month, -1, #rollover_date);
select sum(t.Revenue) as Revenue from (
select sum(bu.value) as Revenue
from bus_category_for bu
join bus_category buc on buc.id=bu.bus_category_id
join bus bu on bu.id=buc.bus_id
where buc.type_id=18 and bu.id=21 and
--Here I want to add a case statement
bu.date between '2015-01-01' and '2015-10-01'
I Guess you need something like this
SELECT Sum(t.Revenue) AS Revenue
FROM (SELECT Sum(bu.value) AS Revenue
FROM bus_category_for bu
JOIN bus_category buc
ON buc.id = bu.bus_category_id
JOIN bus bu
ON bu.id = buc.bus_id
WHERE buc.type_id = 18
AND bu.id = 21
AND ( ( #syssDate = #start_quarter
AND bu.date BETWEEN '2015-01-01' AND '2015-10-01' )
OR ( another date ) ))a
Try something like
WHERE (syssDate = start_quarter AND bu.date between '2015-01-01' and '2015-10-01')
OR (yssDate <> start_quarter AND bu.date between '2016-01-01' and '2016-10-01')
Generally, it's advisable not to use between for dates. It's better to use bu.date >= '2015-01-01' AND bu.date < '2015-10-02'. See here.

why does adding the where statement to this sql make it run so much slower?

I have inherited a stored procedure and am having problems with it takes a very long time to run (around 3 minutes). I have played around with it, and without the where clause it actually only takes 12 seconds to run. None of the tables it references have a lot of data in them, can anybody see any reason why adding the main where clause below makes it take so much longer?
ALTER Procedure [dbo].[MissingReadingsReport] #SiteID INT,
#FormID INT,
#StartDate Varchar(8),
#EndDate Varchar(8)
As
If #EndDate > GetDate()
Set #EndDate = Convert(Varchar(8), GetDate(), 112)
Select Dt.FormID,
DT.FormDAte,
DT.Frequency,
Dt.DayOfWeek,
DT.NumberOfRecords,
Dt.FormName,
dt.OrgDesc,
Dt.CDesc
FROM (Select MeterForms.FormID,
MeterForms.FormName,
MeterForms.SiteID,
MeterForms.Frequency,
DateTable.FormDate,
tblOrganisation.OrgDesc,
CDesc = ( COMPANY.OrgDesc ),
DayOfWeek = CASE Frequency
WHEN 'Day' THEN DatePart(dw, DateTable.FormDate)
WHEN 'WEEK' THEN
DatePart(dw, MeterForms.FormDate)
END,
NumberOfRecords = CASE Frequency
WHEN 'Day' THEN (Select TOP 1 RecordID
FROM MeterReadings
Where
MeterReadings.FormDate =
DateTable.FormDate
And MeterReadings.FormID =
MeterForms.FormID
Order By RecordID DESC)
WHEN 'WEEK' THEN (Select TOP 1 ( FormDate )
FROM MeterReadings
Where
MeterReadings.FormDate >=
DateAdd(d
, -4,
DateTable.FormDate)
And MeterReadings.FormDate
<=
DateAdd(d, 3,
DateTable.FormDate)
AND MeterReadings.FormID =
MeterForms.FormID)
END
FROM MeterForms
INNER JOIN DateTable
ON MeterForms.FormDate <= DateTable.FormDate
INNER JOIN tblOrganisation
ON MeterForms.SiteID = tblOrganisation.pkOrgId
INNER JOIN tblOrganisation COMPANY
ON tblOrganisation.fkOrgID = COMPANY.pkOrgID
/*this is what makes the query run slowly*/
Where DateTable.FormDAte >= #StartDAte
AND DateTable.FormDate <= #EndDate
AND MeterForms.SiteID = ISNULL(#SiteID, MeterForms.SiteID)
AND MeterForms.FormID = IsNull(#FormID, MeterForms.FormID)
AND MeterForms.FormID > 0)DT
Where ( Frequency = 'Day'
And dt.NumberofRecords IS NULL )
OR ( ( Frequency = 'Week'
AND DayOfWeek = DATEPART (dw, Dt.FormDate) )
AND ( FormDate <> NumberOfRecords
OR dt.NumberofRecords IS NULL ) )
Order By FormID
Based on what you've already mentioned, it looks like the tables are properly indexed for columns in the join conditions but not for the columns in the where clause.
If you're not willing to change the query, it may be worth it to look into indexes defined on the where clause columns, specially that have the NULL check
Try replacing your select with this:
FROM
(select siteid, formid, formdate from meterforms
where siteid = isnull(#siteid, siteid) and
meterforms.formid = isnull(#formid, formid) and formid >0
) MeterForms
INNER JOIN
(select formdate from datetable where formdate >= #startdate and formdate <= #enddate) DateTable
ON MeterForms.FormDate <= DateTable.FormDate
INNER JOIN tblOrganisation
ON MeterForms.SiteID = tblOrganisation.pkOrgId
INNER JOIN tblOrganisation COMPANY
ON tblOrganisation.fkOrgID = COMPANY.pkOrgID
/*this is what makes the query run slowly*/
)DT
I would be willing to bet that if you moved the Meterforms where clauses up to the from statement:
FROM (select [columns] from MeterForms WHERE SiteID= ISNULL [etc] ) MF
INNER JOIN [etc]
It would be faster, as the filtering would occur before the join. Also, having your INNER JOIN on your DateTable doing a <= down in your where clause may be returning more than you'd like ... try moving that between up to a subselect as well.
Have you run an execution plan on this yet to see where the bottleneck is?
Random suggestion, coming from an Oracle background:
What happens if you rewrite the following:
AND MeterForms.SiteID = ISNULL(#SiteID, MeterForms.SiteID)
AND MeterForms.FormID = IsNull(#FormID, MeterForms.FormID)
...to
AND (#SiteID is null or MeterForms.SiteID = #SiteID)
AND (#FormID is null or MeterForms.FormID = #FormID)