SQL Server : WHERE clause case with between - sql

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.

Related

Displaying student absent dates

Here is the table I want to display:
tblAttendance table
CustomerId
Id
Attendence
Date
and
tblStudent
CustomerId
Name
Now I want to search by from to date and want absent date.
How can I achieve this?
I tried below code:
ALTER PROCEDURE spExceptDate
AS
declare #StartDate DATE, #EndDate DATE
set #StartDate = '2020-02-15';
set #EndDate = '2020-02-25';
BEGIN
SELECT CustomerId,FirstName+' '+LastName,Date,Attendance
FROM
[dbo].[tblAttendance] att
LEFT JOIN
[dbo].[tblStudent] st
ON att.CustomerId = st.Code
EXCEPT
SELECT CustomerId,FirstName+' '+LastName,Date,Attendance
FROM
[dbo].[tblAttendance] att
LEFT JOIN
[dbo].[tblStudent] st
ON att.CustomerId = st.Code
where att.Date>='2020-02-15' and att.Date<='2020-02-25'
END
GO
i want date for which student absend
Basically what you need is list of possible dates between From and To
DECLARE #StartDate DATE = '2020-02-15',
#EndDate DATE = '2020-02-25' ;
--Create a CTE to get all dates between from and to (you should filter holidays and weekends)
WITH SchoolCalendar (WorkingDay)
AS (SELECT #StartDate
UNION ALL
SELECT DATEADD(DAY, 1, WorkingDay)
FROM SchoolCalendar
WHERE WorkingDay< #EndDate
)
--Use the CTE to determine the Absense records
SELECT st.Code CustomerId, st.FirstName+' '+st.LastName Name,st.WorkingDay Date, COALESCE(Attendance,'A') Attendance
FROM (SELECT * from SchoolCalendar, tblStudent) st
LEFT JOIN [dbo].[tblAttendance] att ON att.Date = st.WorkingDay AND att.CustomerId = st.Code
WHERE st.WorkingDay>=#StartDate and st.WorkingDay<=#EndDate
ORDER BY st.Code, st.WorkingDay
You may need only one query if you want to fetch only absent student names from the given date range
SELECT CustomerId,FirstName+' '+LastName,Date,Attendance
FROM [dbo].[tblAttendance] att
LEFT JOIN [dbo].[tblStudent] st ON att.CustomerId = st.Code
WHERE att.Date>='2020-02-15' and att.Date<='2020-02-25' AND att.Attendance <> 'P'
^^^^^^^^^^^^^^^^^^^^

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

Can this Full Outer Join query be simplified?

I have bill data from two sources. I want to join them to be able to see where there is a record in one set that is not in the other and vice versa. This query does what I want but I feel like it could be written more elegantly? I only want one field for the account number and bill date (M and Y), and then separate fields for the the charges in each source.
DECLARE #BillDate datetime ='2/1/2016'
SELECT ACCT_NO = COALESCE(BPFACCT,CSTACCT) ,
BillDate = COALESCE(BPFBillDate,CSTBillDate) ,
BPFCharge ,
CSTCharge ,
Delta = ROUND(COALESCE(BPFBill.BPFCharge,0)-COALESCE(CSTBill.CSTCharge,0),2)
FROM
(
SELECT
BPFACCT = acct_no ,
BPFBillDate = cast(billdate as date) ,
BPFCharge = SUM(charge)
FROM
cisbill b
JOIN
cisbilldetail bd ON b.billid=bd.billid
WHERE
billdate>=#BillDate
AND
billdate<DATEADD(MONTH, 1, #BillDate)
GROUP BY
acct_no, billdate
) BPFBill
FULL OUTER JOIN
(
SELECT CSTACCT = acct_no ,
CSTBillDate = cast(bill_date as date) ,
CSTCharge = SUM(new_charges)
FROM
cst_bill
WHERE
bill_date>=#BillDate
AND
bill_date<DATEADD(MONTH, 1, #BillDate)
GROUP BY
acct_no, bill_date
) CSTBill
ON BPFBill.BPFACCT=CSTBill.CSTACCT
AND
BPFBill.BPFBillDate=CSTBill.CSTBillDate
Appreciate any feedback!
I feel like this would give you a more accurate result..
DECLARE #StartDate DATETIME = '2/1/2016',
#EndDate DATETIME
SET #EndDate = DATEADD(MONTH, 1, #BillDate)
SELECT ACCT_NO,
MM,
YY,
BPFCharge = SUM(BPFCharge),
CSTCharge = SUM(CSTCharge)
FROM
(
SELECT acct_no,
MM = MONTH(billdate),
YY = YEAR(billdate),
BPFCharge = charge
CSTCharge = 0.00
FROM cisbill b
JOIN cisbilldetail bd ON b.billid = bd.billid
WHERE billdate >= #StartDate
AND billdate < #EndDate
UNION ALL
SELECT acct_no,
MONTH(bill_date),
YEAR(Bill_date),
0.00,
new_charges
FROM cst_bill
WHERE bill_date >= #StartDate
AND bill_date < #EndDate
) t
GROUP BY ACCT_NO,
MM,
YY

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)

MS Access Query problem?

I am using this query:
SELECT D.Generic, D.Ww, D.Dd, D.Plan, c.TotalScan, D.Plan - c.TotalScan AS Balance
FROM TableA D
LEFT JOIN (
SELECT COUNT(a.Specific) AS TotalScan,
b.Generic, a.Dd,a.Ww
FROM TableB a
INNER JOIN TableC b
ON a.Specific = b.Specific
GROUP
BY b.Generic,a.Dd,a.Ww
WHERE DATEDIFF(DAY, a.TransactionDate, GETDATE()) = 0
) c
ON c.Generic = D.Generic
AND D.Ww = c.Ww
AND c.Dd = D.Dd
WHERE DATEDIFF(DAY, c.TransactionDate, GETDATE()) = 0;
to filter all records that is a insert in my sqlserver database.
Now i am having a hard time how can i do it ms access.
1. DATEDIFF(Day, TransactionDate, GetDate()) = 0 -- Not Work on MS Access(Which Filter all Records inserted in current Date)
2. Cant display TotalScan from subquery
Example Output Date:
TransactionDate
3/21/2011 7:26:24 AM
3/21/2011 7:26:24 AM
3/22/2011 7:26:24 AM --
3/22/2011 7:26:28 AM --
3/22/2011 7:26:30 AM --
3/22/2011 7:26:32 AM --
3/22/2011 7:26:35 AM --
if my date today is 3/22/2011 5 records will be displayed.
Thanks in Regards
GetDate() is SQL Server specific, Access has Now() instead.
The DateDiff() function also exists in Access, but the parameter for the interval is different:
DateDiff("d", TransactionDate, Now())
Equivalent of:
DATEDIFF(DAY, c.TransactionDate, GETDATE()) = 0
DATEDIFF("d", c.TransactionDate, Now()) = 0
Regards