SQL Result into one Row - sql

I wrote a sql query like this.
SELECT
TR.TRAN_DATE,
CASE WHEN tr.CR_DR='CR' THEN sum(TR.GL_TRN_AMT) ELSE 0 END AS CR,
CASE WHEN tr.CR_DR='DR' THEN sum(TR.GL_TRN_AMT) ELSE 0 END AS DR
FROM
[COREBANKER1].[dbo].[GL_DAILY_TRN] AS TR
WHERE
TR.GL_CODE = '01010101'
AND TR.BRANCH_CODE = 1000
AND TR.TRAN_DATE BETWEEN '2016-11-01' AND '2017-03-01'
GROUP BY
TR.TRAN_DATE, TR.CR_DR, TR.[BRANCH_CODE]
ORDER BY
TR.TRAN_DATE
The result is this:
Result
but I want DR CR result into one row.

When doing conditional aggregation, the case is the argument to the sum():
SELECT TR.TRAN_DATE,
SUM(CASE WHEN tr.CR_DR = 'CR' THEN TR.GL_TRN_AMT ELSE 0
END) AS CR,
SUM(CASE WHEN tr.CR_DR='DR' THEN TR.GL_TRN_AMT ELSE 0
END) AS DR
FROM [COREBANKER1].[dbo].[GL_DAILY_TRN] TR
WHERE TR.GL_CODE = '01010101' AND
TR.BRANCH_CODE=1000 AND
TR.TRAN_DATE BETWEEN '2016-11-01' AND '2017-03-01'
GROUP BY TR.TRAN_DATE --, TR.[BRANCH_CODE]
ORDER BY TR.TRAN_DATE;
I don't know if you want a separate row for each branch or not. If you do, uncomment out the reference in the GROUP BY.

Related

How to exclude 0 from count()? in sql?

I have a code as below where I want to count number of first purchases for a given period of time. I have a column in my sales table where if the buyer is not a first time buyer, then is_first_purchase = 0
For example:
buyer_id = 456391 is already an existing buyer who made purchases on 2 different dates.
Hence is_first_purchase column will show as 0 as per below.
If i do a count() on is_first_purchase for this buyer_id = 456391 then it should return 0 instead of 2.
My query is as follows:
with first_purchases as
(select *,
case when is_first_purchase = 1 then 'Yes' else 'No' end as first_purchase
from sales)
select
count(case when first_purchase = 'Yes' then 1 else 0 end) as no_of_first_purchases
from first_purchases
where buyer_id = 456391
and date_id between '2021-02-01' and '2021-03-01'
order by 1 desc;
It returned the below which is not an intended output
Appreciate if someone can help explain how to exclude is_first_purchase = 0 from the count, thanks.
Because COUNT function count when the value isn't NULL (include 0), if you don't want to count, need to let CASE WHEN return NULL
There are two ways you can count as your expectation, one is SUM other is COUNT but remove the part of else 0
SUM(case when first_purchase = 'Yes' then 1 else 0 end) as no_of_first_purchases
COUNT(case when first_purchase = 'Yes' then 1 end) as no_of_first_purchases
From your question, I would combine CTE and main query as below
select
COUNT(case when is_first_purchase = 1 then 1 end) as no_of_first_purchases
from sales
where buyer_id = 456391
and date_id between '2021-02-01' and '2021-03-01'
order by 1 desc;
I think that you are using COUNT() when you want SUM().
with first_purchases as
(select *,
case when is_first_purchase = 1 then 'Yes' else 'No' end as first_purchase
from sales)
select
SUM(case when first_purchase = 'Yes' then 1 else 0 end) as no_of_first_purchases
from first_purchases
where buyer_id = 456391
and date_id between '2021-02-01' and '2021-03-01'
order by 1 desc;
You could simplify your query as:
SELECT COUNT(*) AS
FROM sales no_of_first_purchases
WHERE is_first_purchase = 1
AND buyer_id = 456391
AND date_id BETWEEN '2021-02-01' AND '2021-03-01'
ORDER BY 1 DESC;
It is better to avoid the use of functions like IF and CASE when it can be done with WHERE.
The simplest approach for Trino (f.k.a. Presto SQL) is to use an aggregate with a filter:
count(name) FILTER (WHERE first_purchase = 'Yes') AS no_of_first_purchases

Summary result from referring tables

I Have some database tables.one table call GL and has gl_id, gl_type_id, etc. columns.
Other one is gl_tran table and has gl_id, trn_amount, etc. I want to get a summary of gl_type_id of tran_amount. I wrote a query for this.
SELECT GL.CHAT_ACC_ID,GL.CHAT_ACC_NAME,GL.GL_TYPE_ID,GL.GL_TYPE_NAME,
SUM(CASE WHEN tr.CR_DR = 'CR' AND TR.BRANCH_CODE=1000 AND TR.TRAN_DATE<'2000-01-01' THEN TR.GL_TRN_AMT ELSE 0
END) AS CR_BEFORE,
SUM(CASE WHEN tr.CR_DR='DR' AND TR.BRANCH_CODE=1000 AND TR.TRAN_DATE<'2000-01-01' THEN TR.GL_TRN_AMT ELSE 0
END) AS DR_BEFORE,
SUM(CASE WHEN tr.CR_DR = 'CR' AND TR.BRANCH_CODE=1000 AND TR.TRAN_DATE BETWEEN '2000-01-01' AND '2010-01-01' THEN TR.GL_TRN_AMT ELSE 0
END) AS CR_BETWEEN,
SUM(CASE WHEN tr.CR_DR = 'DR' AND TR.BRANCH_CODE=1000 AND TR.TRAN_DATE BETWEEN '2000-01-01' AND '2010-01-01' THEN TR.GL_TRN_AMT ELSE 0
END) AS DR_BETWEEN
FROM [COREBANKER1].[dbo].[GL_MAIN] as GL
LEFT JOIN [COREBANKER1].[dbo].[GL_DAILY_TRN] AS TR ON GL.GL_ID = TR.GL_CODE
GROUP BY GL.CHAT_ACC_ID,GL.CHAT_ACC_NAME,GL.GL_TYPE_ID,GL.GL_TYPE_NAME
ORDER BY GL.GL_ID
But this result has only if transaction happens for particular gl. I want summary for all GL.CHAT_ACC_ID. How should I change my query for that result?
I think you just need to add below statement in select...
Sum(TR.GL_TRN_AMT) over() as TotalSum
I found the solution... :D
SELECT CG.CHART_ACC_ID,CG.CHART_ACC_NAME,CG.GL_TYPE_ID,CG.GL_TYPE_NAME,
SUM(CASE WHEN tr.CR_DR = 'CR' AND TR.BRANCH_CODE=1000 AND TR.TRAN_DATE<'2000-01-01' AND CG.CHART_ACC_ID=GL.CHAT_ACC_ID AND TR.GL_CODE=GL.GL_ID THEN TR.GL_TRN_AMT ELSE 0
END) AS CR_BEFORE,
SUM(CASE WHEN tr.CR_DR='DR' AND TR.BRANCH_CODE=1000 AND TR.TRAN_DATE<'2000-01-01' AND CG.CHART_ACC_ID=GL.CHAT_ACC_ID AND TR.GL_CODE=GL.GL_ID THEN TR.GL_TRN_AMT ELSE 0
END) AS DR_BEFORE,
SUM(CASE WHEN tr.CR_DR = 'CR' AND TR.BRANCH_CODE=1000 AND TR.TRAN_DATE BETWEEN '2000-01-01' AND '2010-01-01' AND CG.CHART_ACC_ID=GL.CHAT_ACC_ID AND TR.GL_CODE=GL.GL_ID THEN TR.GL_TRN_AMT ELSE 0
END) AS CR_BETWEEN,
SUM(CASE WHEN tr.CR_DR = 'DR' AND TR.BRANCH_CODE=1000 AND TR.TRAN_DATE BETWEEN '2000-01-01' AND '2010-01-01' AND CG.CHART_ACC_ID=GL.CHAT_ACC_ID AND TR.GL_CODE=GL.GL_ID THEN TR.GL_TRN_AMT ELSE 0
END) AS DR_BETWEEN
FROM[COREBANKER1].[dbo].[GL_DAILY_TRN] AS TR, [COREBANKER1].[dbo].[GL_MAIN] as GL full JOIN [COREBANKER1].[dbo].GL_CHART_ACC AS CG
ON GL.CHAT_ACC_ID=CG.CHART_ACC_ID
GROUP BY CG.CHART_ACC_ID,CG.CHART_ACC_NAME,CG.GL_TYPE_ID,CG.GL_TYPE_NAME
ORDER BY CG.CHART_ACC_ID

Select with subquery select not working

I keep getting that error on this code. I am not using EXISTS.Please Help.
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.
SQL:
If ISDATE(#grpsearch) = 1
SELECT grp.GroupID,
vlanlist.InternetType,
grp.GroupName, cast(grp.StartDateTime as date) as StartDate,
convert(varchar,cast(grp.StartDateTime as time),100) as starttime,
(select case when datepart(hh,convert(datetime,grp.StartDateTime)) > 12 then datepart(hh,convert(datetime,grp.StartDateTime))-12
else case when datepart(hh,convert(datetime,grp.StartDateTime)) = 0 then '12' else datepart(hh,convert(datetime,grp.StartDateTime)) end end as starthour,
datepart(mi,convert(datetime,grp.StartDateTime)) as startmin, case when datepart(hh,convert(datetime,grp.StartDateTime)) >= 12 then 'PM' else 'AM' end as startperiod),
cast(grp.enddatetime as date) as EndDate,
convert(varchar,cast(grp.EndDateTime as time),100) as EndTime,
grp.UserInitials,
grp.UserComments,
roomlist.RoomName,
jacklist.JackNumber
FROM a_Cisco.dbo.grp_internet as grp left outer join
dbo.jacklist as jacklist ON grp.intJack = jacklist.intJack left outer join
dbo.roomlist as roomlist ON grp.intRoom = roomlist.intROom left outer join
dbo.vlanlist as vlanlist ON grp.VlanID = vlanlist.VlanID
WHERE (convert(varchar,cast(grp.StartDateTime as date),100) = #grpsearch)
The problem is this part of the query:
(select case when datepart(hh,convert(datetime,grp.StartDateTime)) > 12
then datepart(hh,convert(datetime,grp.StartDateTime))-12
else case when datepart(hh,convert(datetime,grp.StartDateTime)) = 0
then '12' else datepart(hh,convert(datetime,grp.StartDateTime))
end
end as starthour,
First, you don't need the select at all. Second, you are missing the closing parentheses ()). I would suggest:
(case when datepart(hh,convert(datetime,grp.StartDateTime)) > 12
then datepart(hh,convert(datetime,grp.StartDateTime))-12
else (case when datepart(hh,convert(datetime,grp.StartDateTime)) = 0
then '12'
else datepart(hh,convert(datetime,grp.StartDateTime))
end)
end) as starthour,

SQL Query: Cannot perform aggregate functions on sub queries

I have the following SQL query
SELECT
[Date],
DATENAME(dw,[Date]) AS Day,
SUM(CASE WHEN ChargeCode IN (SELECT ChargeCode FROM tblChargeCodes WHERE Chargeable = 1) THEN Units ELSE 0 END) ChargeableTotal,
SUM(CASE WHEN ChargeCode IN (SELECT ChargeCode FROM tblChargeCodes WHERE Chargeable = 0) THEN Units ELSE 0 END) NotChargeableTotal,
SUM(Units) AS TotalUnits
FROM
tblTimesheetEntries
WHERE
UserID = 'PJW'
AND Date >= '2013-01-01'
GROUP BY
[Date]
ORDER BY
[Date] DESC;
But I get the error message:
Cannot perform an aggregate function on an expression containing an aggregate or a subquery.
Because I am using sub queries in the Case Else Summation.
How can I revise my query to get 2 x Sums of [Units] one for Chargeable = true, and one for Chargeable = false, even though the Chargeable field is in a different table to all the other information. The two tables are linked by ChargeCode which appears in both tblTimesheetEntries and tblChargeCodes.
Have you tried joining the tables on the chargeCode:
SELECT e.[Date],
DATENAME(dw,e.[Date]) AS Day,
SUM(CASE WHEN c.Chargeable = 1 THEN e.Units ELSE 0 END) ChargeableTotal,
SUM(CASE WHEN c.Chargeable = 0 THEN e.Units ELSE 0 END) NotChargeableTotal,
SUM(e.Units) AS TotalUnits
FROM tblTimesheetEntries e
LEFT JOIN tblChargeCodes c
on e.ChargeCode = c.ChargeCode
WHERE e.UserID = 'PJW'
AND e.Date >= '2013-01-01'
GROUP BY e.[Date]
ORDER BY e.[Date] DESC;

One date check for entire query

I have the following query:
select
fp.id,
fr.id,
sum(case
when to_date(fp.offered_date) BETWEEN TO_DATE( :ad_startdate, 'YYYY-MM-DD')
AND TO_DATE(:ad_enddate, 'YYYY-MM-DD') and fp.result <> 'E'
then 1
else 0
end) total,
sum(case when fp.result = 'G'
and to_date(fp.offered_date) >= :ad_startdate
and to_date(fp.offered_date) <= :ad_enddate then 1 else 0 end) colorgreen,
sum(case when fp.resultat = 'R'
and to_date(fp.offered_date) >= :ad_startdate
and to_date(fp.offered_date) <= :ad_enddate then 1 else 0 end) colorred
FROM
fruit_properties fp, fruit fr
WHERE
fp.id = fr.id
GROUP BY
fp.id, fr.id
I'm checking dates 1 time for each sum column and have a feeling this can be made once somehow? Right now if I check only once at the total column, then colorgreen + colorred might be larger than the total since it counts no matter what date they have.
Can my query be enhanced somehow?
you can simplify like this. but PLEASE check your SQL. you're mixing TO_DATE and CHAR datatypes. this will only end in disaster.
eg you have:
when to_date(fp.offered_date) BETWEEN TO_DATE( :ad_startdate, 'YYYY-MM-DD')
AND TO_DATE(:ad_enddate, 'YYYY-MM-DD')
vs
sum(case when fp.result = 'G'
and to_date(fp.offered_date) >= :ad_startdate
in one case you are TO_DATE'ing ad_startdate but not another (so is it a date already or not?). you are also TO_DATEing the column but crucially WITHOUT a format mask. is the column really a VARCHAR datatype? if so you really should not store dates as anything but DATEs.
anyway assuming the column is a DATE datatype and the binds are of type DATE..
select fruit_prop_Id,fruit_id,
sum(case when result != 'E' then within_offer else 0 end) total,
sum(case when result = 'R' then within_offer else 0 end) colorred,
sum(case when result = 'G' then within_offer else 0 end) colorgreen
from (select fp.id fruit_id,
fr.id fruit_prop_Id,
fp.result,
case
when fp.offered_date >= :ad_startdate
and fp.offered_date <= :ad_enddate then 1 else 0 end within_offer
from fruit_properties fp, fruit fr
where fp.id = fr.id)
group by fruit_id, fruit_prop_Id
You can put the date check in the where clause:
select
fp.id,
fr.id,
sum(case when and fp.result <> 'E' then 1 else 0 end) total,
sum(case when fp.result = 'G' then 1 else 0 end) colorgreen,
sum(case when fp.resultat = 'R' then 1 else 0 end) colorred
FROM
fruit_properties fp, fruit fr
WHERE
fp.id = fr.id
AND to_date(fp.offered_date) >= :ad_startdate
AND to_date(fp.offered_date) <= :ad_enddate
GROUP BY
fp.id, fr.id
Edit: as pointed out in the comments, this query will filter out ids which doesn't have any offer dates in the given interval.