Case and Count sql server 2008 - sql

I need to return the value '0' for null results and am having a bit of difficulty. I have tried several combinations, but this is my stored procedure, before accounting for the nulls, as I have gotten nowhere. I need my total to appear as '0' for days there are no appointments for each warehouse. HELP!!!! I'm very stuck.
SELECT cis.districtname AS [Warehouse],
CONVERT(VARCHAR(10), cca.appointment_date, 101) AS [Appt Date],
COUNT(*) AS [Total]
FROM [pscgdassql\dasdb].das_scg.[dbo].[cc.callcenteractivity] cca
LEFT JOIN [pscgdassql\dasdb].das_scg.core.WorkOrder wo
ON cca.apptheaderworkorder = wo.workorderid
LEFT JOIN [pscgdassql\dasdb].das_scg.cis.warehouses cis
ON wo.SvtBaseCode = cis.SVCBaseCode
AND wo.Section = cis.section
WHERE CAST(cca.appointment_date AS DATE) >= CAST(GETDATE() AS DATE)
AND cca.appointment_date <> ''
AND cca.appointment_date IS NOT NULL
AND cca.appointment_date <> '01/01/1900'
AND wo.WorkOrderStatusInd NOT IN ( 5, 6 )
GROUP BY cis.districtname,
CONVERT(VARCHAR(10), cca.appointment_date, 101)

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.

Is it possible to add second where condition to select this same data but from other date range?

I have two tables in SQL Server.
I want to select DeptCode, DeptName, YearToDate, PeriodToDate (2 months for example) and group it by DeptCode.
There is a result which I want to get:
In YTD column I want to get sum of totalCost since 01/01/actualYear.
In PTD column I want to get the sum from last two months.
I created a piece of code which shows me correct YTD cost but I don't know how I can add next one for getting total cost for other date range. Is it possible to do this?
SELECT
d.DeptCode,
d.DeptName,
SUM(s.TotalCost) as YTD
FROM [Departments] AS d
INNER JOIN Shipments AS s
ON d.DeptCode= s.DeptCode
WHERE s.ShipmentDate BETWEEN DateAdd(yyyy, DateDiff(yyyy, 0, GetDate()), 0)
AND GETDATE()
GROUP BY d.DeptCode, d.DeptName
Your expected output doesn't match 2 months, but here's the code to accomplish what you want. You just have to add a SUM(CASE...) on the 2nd condition.
SELECT
d.DeptCode,
d.DeptName,
SUM(s.TotalCost) as YTD,
SUM(CASE WHEN s.ShipmentDate >= DATEADD(month, -2, GETDATE()) then s.TotalCost else 0 END) as PTD
FROM [Departments] AS d
INNER JOIN Shipments AS s
ON d.DeptCode= s.DeptCode
WHERE Year(s.ShipmentDate) = Year(GETDATE())
GROUP BY d.DeptCode, d.DeptName
Just add one more column that returns 0 when not in the two-month range, e.g. SUM(CASE WHEN (date check) THEN (amount) ELSE 0 END). Check out the fifth line:
SELECT
d.DeptCode,
d.DeptName,
SUM(s.TotalCost) as YTD,
SUM(CASE WHEN DateDiff(MONTH, s.ShipmentDate, GetDate()) < 2 THEN s.TotalCost ELSE 0 END) PTD,
FROM [Departments] AS d
INNER JOIN Shipments AS s
ON d.DeptCode= s.DeptCode
WHERE s.ShipmentDate BETWEEN DateAdd(yyyy, DateDiff(yyyy, 0, GetDate()), 0)
AND GETDATE()
GROUP BY d.DeptCode, d.DeptName
Try this one :
nbr_last2month_ AS
(
SELECT DISTINCT
Sum(s.[TotalCost]) AS 'PTD',
s.DeptCode,
s.DeptName
FROM [Shipements] s
LEFT JOIN [Departements] d ON d.[DeptCode] = s.[DeptCode]
WHERE Year(date_) LIKE Year(GETDATE())
AND MONTH(ShipementDate) LIKE Month(Getdate()) - 2
Group by DeptCode
),
nbr_YTD_ AS
(
SELECT DISTINCT
Sum(s.[TotalCost]) AS 'YTD',
s.DeptCode,
s.DeptName
FROM [Shipements] s
LEFT JOIN [Departements] d ON d.[DeptCode] = s.[DeptCode]
WHERE Year(ShipementDate) LIKE Year(GETDATE())
Group by DeptCode
),
SELECT
A.DeptCode,
A.DeptName,
YTD,
PTD
FROM nbr_YTD_ A
LEFT JOIN nbr_last2month_ B on B.DeptCode = A.DeptCode
ORDER BY DeptCode

Adding a max date subquery to a group by clause

I need to add a max transactional date to this report, so I can see the most recent transaction date for a patient who does not fall under the parameters in the query. This report will be going into a crystal report and I plan to put the last date of service date in the group header for each patient. The code below is to get the max date for each patient. I need the results inserted, so it takes the patients who fall under the below report and gives their max date. Regardless of what is entered for a date. Thank you in advance. SQL Server 2005.
select
patient_id,
Max(proc_chron)
from patient_clin_tran pct
group by patient_id
The Code for the transaction
select patient_id,
(select p.case_status from patient p where p.patient_id = btb.patient_id and p.episode_id = (select max(episode_id) from patient p2 where p2.patient_id = p.patient_id)) as 'Status',
(select p.lname +', '+ p.fname from patient p where p.patient_id = btb.patient_id and p.episode_id = (select max(episode_id) from patient p2 where p2.patient_id = p.patient_id)) AS 'client',
Coverage_plan_id,
(select proc_code from billing_transaction bt where bt.clinical_transaction_no = btb.clinical_transaction_no and bt.coverage_plan_id=btb.coverage_plan_id and bt.coverage_plan_id = btb.coverage_plan_id) as 'Procedure',
proc_chron,
(select billing_amt from billing_transaction bt where bt.clinical_transaction_no = btb.clinical_transaction_no and bt.coverage_plan_id = btb.coverage_plan_id) as 'Billing Amount',
balance_amount,
(select max (accounting_date) from billing_ledger bl where bl.clinical_transaction_no = btb.clinical_transaction_no and subtype = 'pa' and bl.coverage_plan_id = 'standard') as 'Last Payment on Trans',
(select max (instrument_date) from payment p where p.patient_id = btb.patient_id and p.coverage_plan_id = 'standard') as 'Last Payment on Acct',
(select sum(balance_amount) from billing_transaction_balance btb2 where btb2.patient_id=btb.patient_id and btb2.coverage_plan_id=btb.coverage_plan_id and proc_chron <= CONVERT(CHAR(6), DATEADD(year, -1, DATEDIFF(day, 0,GETDATE())), 112) + '01' and btb2.coverage_plan_id in('standard')) AS 'Balance'
from billing_transaction_balance btb
where proc_chron <= CONVERT(CHAR(6), DATEADD(year, -1, DATEDIFF(day, 0, GETDATE())), 112) + '01' and coverage_plan_id in('standard')
group by patient_id, proc_chron, coverage_plan_id, balance_amount, clinical_transaction_no
In your transaction code, you need to add all the Select columns which are not being aggregated to the Group By. I count 8 non-aggregated columns in the Select statement, so you must have all 8 in the Group By.

I have two tables with common Quote_No and I need to sum Qty in Quote_Items with Required by Date in Table Quotes

I am trying to get the sum of "Qty" in a Table A called "Quote_Items" based on a "Required_by_Date" from Table B called Quotes. Both tables have a common "Quote_No" The required date is one month ago.
I have used the following but it produces a NULL, but I cannot see why
select sum(Qty)
from quotes.Quote_Items_Quantities
left outer join quotes.Quotes on (Quote_Required_by_Date = Qty)
WHERE (DatePart(yy, Quote_Required_by_Date) = DatePart(yy, DateAdd(m,1,getdate()))) and
datepart(m,Quote_Required_by_Date) = datepart(m,dateadd(m,1,getdate()))
Any suggestions what I am doing wrong here.
Try this:
SELECT SUM(i.Qty)
FROM Quote_Items i
JOIN Quotes q on i.Quote_No = q.Quote_No
AND CONVERT(varchar, q.Required_by_Date, 112) = CONVERT(varchar, DATEADD(month, -1, getdate()), 112)
or this (equivalent without using JOIN)
SELECT SUM(i.Qty)
FROM Quote_Items i
WHERE EXISTS(SELECT 1 FROM Quotes WHERE Quote_No = i.Quote_No AND CONVERT(varchar, Required_by_Date, 112) = CONVERT(varchar, DATEADD(month, -1, getdate()), 112))
Your query is producing NULL because of the join condition. You have
on Quote_Required_by_Date = Qty
However, the date is not going to match the quantity. Instead, you need to match on the Quote_No, according to your question:
select sum(Qty)
from quotes.Quote_Items_Quantities qiq left outer join
quotes.Quotes q
on q.Quote_Required_by_Date = qiq.Qty
WHERE (DatePart(yy, Quote_Required_by_Date) = DatePart(yy, DateAdd(m,1,getdate()))) and
datepart(m,Quote_Required_by_Date) = datepart(m,dateadd(m,1,getdate()));
You can also simplify your query by using the month() and year() functions:
select sum(Qty)
from quotes.Quote_Items_Quantities qiq left outer join
quotes.Quotes q
on q.Quote_Required_by_Date = qiq.Qty
WHERE year(Quote_Required_by_Date) = year(DateAdd(m, 1, getdate()) and
month(Quote_Required_by_Date) = month(dateadd(m,1,getdate());
Finally, you mind find it useful to use group by and get the results for many months:
select year(Quote_Required_by_Date), month(Quote_Required_by_Date), sum(Qty)
from quotes.Quote_Items_Quantities qiq left outer join
quotes.Quotes q
on q.Quote_Required_by_Date = qiq.Qty
group by year(Quote_Required_by_Date), month(Quote_Required_by_Date)
order by 1 desc, 2 desc;

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)