How to use case expression and min() with group by - sql

The following query when I that execute
SELECT St.FirstName,St.LastName,
CASE
WHEN St.ISPackage='N' THEN Min(St.VisitingDate)
WHEN St.ISPackage='Y' THEN St.VisitingDate
END AS VisitingDate
FROM SalesTransaction As St
(...inner join and where clause)
GROUP BY St.FirstName,St.LastName, St.VisitingDate
If I use St.VisitingDate in Group By the result is duplicated.
If not used St.VisitingDate in Group By show error
invalid in the select list because it is not contained in either an aggregate function
How can I solve this problem?

I suspect that you want to group by name and get the visit date when ISPackage is "Y", and fallback on the earliest visit date if there is no date where ISPackage is "Y".
If so, you can do:
SELECT St.FirstName,St.LastName,
COALESCE(MIN(CASE WHEN St.ISPackage = 'Y' THEN St.VisitingDate END), MIN(St.VisitingDate)) VisitingDate
FROM SalesTransaction As St
-- (...inner join and where clause)
GROUP BY St.FirstName,St.LastName

you can use below SQL-
I calculated min date using a subquery.
SELECT St.FirstName,St.LastName,
CASE
WHEN St.ISPackage='Y' THEN St.VisitingDate
ELSE min_dt.min_VisitingDate
END AS VisitingDate
FROM
SalesTransaction As St
(...inner join and where clause)
left join (select St.FirstName,St.LastName, min(St.VisitingDate) min_VisitingDate from SalesTransaction group by St.FirstName,St.LastName) min_dt
ON St.FirstName =min_dt.FirstName ,St.LastName =min_dt.LastName

Related

Trying to count number of complaint, cause, corrections

I am trying to create a query with the following fields, that counts the number of Complaints, causes, and corrections show up in the data.
My current error: Select non-aggregate values must be part of the associated group.
I am very new to SQL queries, and am not sure what else I'm missing. All I've done is merged to queries, and seem to be missing something.
select L.Case_ID,
L.Case_Line_ID,
A.Dealer_ID,
M.DealerCode,
H.DealerName,
substr(L.Estimate_Created_At,1,7) as CaseMonth,
count(distinct L.Complaint) as Complaint,
count(distinct C.Cause) as Cause,
count(distinct C.Correction) as Correction
from Decisiv_Tables_Prod.Stg_Decisiv_LineItems L
join Decisiv_Tables_Prod.Stg_Decisiv_Cases A on L.Case_ID = A.Case_ID
join Decisiv_Tables_Prod.Rpt_DecisivDealerMap M on A.Dealer_ID = M.DecisivDealerID
and cast(substr(L.Estimate_Created_At,1,10) as date format 'YYYY-MM-DD') between M.EffectiveStartDate and coalesce(M.EffectiveEndDate, cast('2099-12-31' as date format 'YYYY-MM-DD'))
join Decisiv_Tables_Prod.Rpt_DealerDirectoryHierarchy H on M.DealerCode = H.DealerCode
join Decisiv_Tables_Prod.Stg_Decisiv_LineItems_Clobs C on C.Case_ID = L.Case_ID
and C.Case_Line_ID = L.Case_Line_ID
group by 1,2,3,4,5
Looking to get a table with the following data example:
Dealer ID, Dealer Code, Dealer Name, Case Month, Count of Case_ID, Count of Case_Line_ID, Count of Complaint, Count of Cause, Count of Correction
You have six unaggregated columns:
select L.Case_ID,
L.Case_Line_ID,
A.Dealer_ID,
M.DealerCode,
H.DealerName,
substr(L.Estimate_Created_At,1,7) as CaseMonth,
These should all be in the group by:
group by L.Case_ID, L.Case_Line_ID, A.Dealer_ID,
M.DealerCode, H.DealerName,
substr(L.Estimate_Created_At,1,7) as CaseMonth
As Gordon wrote, the GROUP BY list doesn't match your Select, you need to either remove both Case_ID & Case_Line_ID or aggregate them:
SELECT
A.Dealer_ID,
M.DealerCode,
H.DealerName,
Substr(L.Estimate_Created_At,1,7) AS CaseMonth,
Count(L.Case_ID), -- distinct ?
Count(L.Case_Line_ID), -- distinct ?
Count(DISTINCT L.Complaint) AS Complaint,
Count(DISTINCT C.Cause) AS Cause,
Count(DISTINCT C.Correction) AS Correction
FROM Decisiv_Tables_Prod.Stg_Decisiv_LineItems AS L
JOIN Decisiv_Tables_Prod.Stg_Decisiv_Cases AS A
ON L.Case_ID = A.Case_ID
JOIN Decisiv_Tables_Prod.Rpt_DecisivDealerMap AS M
ON A.Dealer_ID = M.DecisivDealerID
AND Cast(Substr(L.Estimate_Created_At,1,10) AS DATE FORMAT 'YYYY-MM-DD') BETWEEN M.EffectiveStartDate AND Coalesce(M.EffectiveEndDate, DATE '2099-12-31')
JOIN Decisiv_Tables_Prod.Rpt_DealerDirectoryHierarchy AS H
ON M.DealerCode = H.DealerCode
JOIN Decisiv_Tables_Prod.Stg_Decisiv_LineItems_Clobs AS C
ON C.Case_ID = L.Case_ID
AND C.Case_Line_ID = L.Case_Line_ID
GROUP BY
A.Dealer_ID,
M.DealerCode,
H.DealerName,
CaseMonth
I simplified cast('2099-12-31' as date format 'YYYY-MM-DD') to DATE '2099-12-31' and used the column names/aliases in Group By (recommended over 1,2,3,4 in production code).
As Distinct is quite expensive check if you actually need to add it to those counts.

Teradata SQL CASE Statement with multiple conditions

I have the below SQL query -
select distinct HospitalAcctID,
AdmitDate,
DischargeDate,
PatMRN,
Pat_id,
ICD,
MedCenter,
(case when SeqCount =1 and AdmitDate > '06/01/2013' and AdmitDate < '06/01/2018' then 1 else null end ) Firstdiag
from
(
select distinct acct.HSP_ACCOUNT_ID as HospitalAcctID,
cast(acct.ADM_DATE_TIME as date format 'mm/dd/yyyy') as AdmitDate,
cast(acct.DISCH_DATE_TIME as date format 'mm/dd/yyyy') as DischargeDate,
pat.pat_mrn_id as PatMRN,
pat.pat_id as Pat_id,
REF_BILL_CODE as ICD,
grp7.NAME AS MedCenter,
row_number() over (partition by PatMRN order by AdmitDate) as SeqCount
from acct
inner join pat on pat.pat_id = acct.pat_id
inner join hspenc on hspenc.CSN_ID = acct.CSN_ID
inner join dx on acct.ACCOUNT_ID = dx.ACCOUNT_ID and line = 1
inner join edg on dx.DX_ID = edg.DX_ID
inner join loc on loc.LOC_ID = acct.LOC_ID
inner join grp7 ON loc.RPT_GRP_SEVEN = grp7.RPT_GRP_SEVEN
where
grp7.NAME = 'SMC AREA'
and ADMIT_CONF_STAT_C in ('1','4')
and (edg. REF_BILL_CODE in ('431',
'431')
)
and ADT_PAT_CLASS_C in ('1204','12113')
order by AdmitDate;
)Admit
But I am getting the below syntax error -
Syntax error, expected something like an 'EXCEPT' keyword, 'UNION' Keyword or a 'MINUS' keyword between 'AdmitDate' and ','
In the outer select statement, I am trying to get the min (first ) date when the was first diagnosed. I also want to get only the patients who were diagnosed between 6/2013 to 6/2018 which is why I have the CASE statement. But the CASE statement is giving me error.
As #BarbarosĂ–zhan already wrote, remove the last line order by AdmitDate; in the Derived Table.
But there's no need for ROW_NUMBER:
select distinct acct.HSP_ACCOUNT_ID as HospitalAcctID,
cast(acct.ADM_DATE_TIME as date format 'mm/dd/yyyy') as AdmitDate,
cast(acct.DISCH_DATE_TIME as date format 'mm/dd/yyyy') as DischargeDate,
pat.pat_mrn_id as PatMRN,
pat.pat_id as Pat_id,
REF_BILL_CODE as ICD,
grp7.NAME AS MedCenter,
case when -- current rows is first row
min(AdmitDate)
over (partition by PatMRN) = AdminDate
-- current row within date range
and AdminDate >= DATE '2013-06-01' and AdmitDate < DATE '2018-06-01'
then 1
else null
end as Firstdiag
from acct
inner join pat on pat.pat_id = acct.pat_id
inner join hspenc on hspenc.CSN_ID = acct.CSN_ID
inner join dx on acct.ACCOUNT_ID = dx.ACCOUNT_ID and line = 1
inner join edg on dx.DX_ID = edg.DX_ID
inner join loc on loc.LOC_ID = acct.LOC_ID
inner join grp7 ON loc.RPT_GRP_SEVEN = grp7.RPT_GRP_SEVEN
where
grp7.NAME = 'SMC AREA'
and ADMIT_CONF_STAT_C in ('1','4')
and (edg. REF_BILL_CODE in ('431',
'431')
)
and ADT_PAT_CLASS_C in ('1204','12113')
order by AdmitDate;
I also switched to a Standard SQL date literal DATE '2013-06-01' instead of '06/01/2013'. There's only one possible format for the former (DATE 'YYYY-MM-DD') while the latter depends on the FORMAT of the base column and might fail when it changes (of course not in your query, because you defined it in the CAST).

DATEDIFF in Group by causing error

I am posting it a new question as previous question has changed a bit. I am using this query:
SELECT DATEDIFF(SECOND,servicestart,CheckinTime) abondendedTime FROM Location L INNER JOIN
Interaction I
ON L.Id = I.IdLocation
WHERE ServiceEnd = '00:00:00.000'
GROUP BY L.Id, L.Description,DATEDIFF(SECOND,servicestart,CheckinTime)
and it is returning 700 rows where as I don't need this part
DATEDIFF(SECOND,servicestart,CheckinTime) in GROUP BY but If I don't put it in GROUP BY, I get error:
Column 'Interaction.ServiceStart' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
I want this result set
http://prntscr.com/f993xe
I need to do these calculations.
http://prntscr.com/f995dk
I have done this part
SELECT L.Id,
L.Description AS 'Location',
COUNT(L.Id) Interactions,
SUM(CASE WHEN I.ServiceEnd = '00:00:00.000' THEN 1 ELSE 0 END) Abandoned,
(SUM(CASE WHEN I.ServiceEnd = '00:00:00.000' THEN 1 ELSE 0 END) *100)/COUNT(I.Id) AbandonedPercent
FROM Location L
INNER JOIN Interaction I
ON L.Id = I.IdLocation
GROUP BY L.Id,L.Description
and need to calculate
Average Abandon Time,Members,Repeat Members,Repeat Visits,Repeat/Interaction,Average Wait,Average Service
Above first query is for Average Abandon Time
I think this is what you want:
SELECT L.Id, L.Description,
SUM(DATEDIFF(SECOND, servicestart, CheckinTime)) as abondendedTime
FROM Location L INNER JOIN
Interaction I
ON L.Id = I.IdLocation
WHERE ServiceEnd = '00:00:00.000'
GROUP BY L.Id, L.Description;
Unlike your previous question, the column in the WHERE is different from the column used for the DATEDIFF().

Left Join on subquery

Can someone help me with this query? In the subquery P, a fiscal year exists where the same year does not exist in BudgetActivityDetailCurrentBiennium. I need this query to show a null value for Amount in that year. Currently that year does not show up at all.
SELECT
P.FiscalYear
,P.BudgetNbr
,SUM(sec.BudgetActivityDetailCurrentBiennium.TranAmount) AS Amount
FROM
(SELECT
sec.BudgetIndexCurrentBiennium.BudgetNbr
,AVG(CAST(sec.BudgetIndexCurrentBiennium.BienniumYear AS INT)+1) AS FiscalYear
FROM
sec.BudgetIndexCurrentBiennium
GROUP BY
sec.BudgetIndexCurrentBiennium.BudgetNbr
UNION ALL
SELECT
sec.BudgetIndexCurrentBiennium.BudgetNbr
,AVG(CAST(sec.BudgetIndexCurrentBiennium.BienniumYear AS INT)+2) AS FiscalYear
FROM
sec.BudgetIndexCurrentBiennium
GROUP BY
sec.BudgetIndexCurrentBiennium.BudgetNbr) AS P
LEFT JOIN sec.BudgetActivityDetailCurrentBiennium
ON
P.BudgetNbr = sec.BudgetActivityDetailCurrentBiennium.BudgetNbr
AND P.FiscalYear = sec.BudgetActivityDetailCurrentBiennium.FiscalYear
WHERE sec.BudgetActivityDetailCurrentBiennium.BudgetNbr = '076036'
GROUP BY
P.FiscalYear
,P.BudgetNbr
I think the problem is your WHERE clause,
WHERE sec.BudgetActivityDetailCurrentBiennium.BudgetNbr = '076036'
which applies to the SELECT as a whole, not just (as I guess you intend) to the left join.
Change the WHERE to an AND. That should do the trick.

Oracle Max Date query

I have a table called maximo_audit and I am trying to only count the most recent actiondate record with an approvalstatus of N. I wrote this query but it is taking forever to run
SELECT COUNT (*)
FROM (SELECT MAX (actiondate)
FROM timedetail t JOIN maximo_audit m ON m.recordid = t.quantity
WHERE approvalstatus = 'N'
AND t.tsdate BETWEEN '8-dec-2013' AND '21-dec-2013'
AND task2 IS NOT NULL
--and recordid = '1781891'
GROUP BY m.recordid
HAVING MAX (actiondate) IN (SELECT MAX (actiondate)
FROM maximo_audit ma
WHERE ma.recordid = m.recordid))
Often using explicit joins helps the optimizer. You can also replace the subquery with a simpler count(distinct).
SELECT COUNT(DISTINCT m.recordid)
FROM timedetail t JOIN
maximo_audit m
ON m.recordid = t.quantity JOIN
(select ma.recordid, max(actiondate) as actiondate
from maximo_audit ma
group by ma.recordid
) ma
on ma.recordid = m.recordid and ma.actiondate = m.actiondate
WHERE approvalstatus = 'N' AND
t.tsdate BETWEEN '8-dec-2013' AND '21-dec-2013' AND
task2 IS NOT NULL;
The having clause can be replaced with a join because when the maximum of the action date equals something, then one of the action dates will match that value.