Rows to columns in SQL Server - sql

I'm developping a tool which generates an excel table with SQL results.
I have several days, several payment methods (fe: credit card, check, species) and several sums.
I am doing this request :
SELECT TE.DATE AS 'JOUR', SUM(TE.TOTAL_TTC) AS 'CA TTC', ME.LIBELLE AS 'LIBELLE'
FROM TICKET TE
INNER JOIN MODE_REGLEMENT ME ON ME.CODE = TE.MODE_REGLEMENT
GROUP BY TE.DATE, ME.LIBELLE
(MODE_REGLEMENT means payment method)
And i have this result :
**JOUR** **CA TTC** **LIBELLE**
07/03/2014 1409.66 CREDIT CARD
07/03/2014 70 CHECK
07/03/2014 1393.31 SPECIES
08/03/2014 3368.07 CREDIT CARD
08/03/2014 599.44 SPECIES
09/03/2014 268.7 CREDIT CARD
09/03/2014 174.62 CHECK
But i'm searching to generate something like that :
**JOUR** **CA TTC** **CREDIT CARD** **CHECK** **SPECIES**
07/03/2014 2872.97 1409.66 70 1393.31
08/03/2014 3967.51 3368.07 0 599.44
09/03/2014 443.32 268.7 174.62 0
The column 'CA TTC' will be the sum of each payment methods.
Can you please help me to do a request (for SQL Server) to have the result i want.
Thank you a lot !
(sorry for the bad english i'm french)

You need to use PIVOT
Find the total per JOUR using SUM over() in pivot source query.
SELECT jour,
CA_TTC=total,
[CREDIT CARD]=Isnull([CREDIT CARD], 0),
[CHECK]=Isnull([CHECK], 0),
[SPECIES]=Isnull([SPECIES], 0)
FROM (SELECT *,
Sum(CA_TTC)OVER(partition BY JOUR) total
FROM Your_result) a
PIVOT (Max(CA_TTC)
FOR LIBELLE IN([CREDIT CARD],
[CHECK],
[SPECIES])) pv
SQLFIDDLE DEMO

Another method is to use conditional aggregation or SUM(CASE WHEN ... END):
;WITH CTE([JOUR], [CA TTC], [LIBELLE]) AS(
SELECT
TE.DATE AS 'JOUR',
SUM(TE.TOTAL_TTC) AS 'CA TTC',
ME.LIBELLE AS 'LIBELLE'
FROM TICKET TE
INNER JOIN MODE_REGLEMENT ME ON ME.CODE = TE.MODE_REGLEMENT
GROUP BY TE.DATE, ME.LIBELLE
)
SELECT
[JOUR],
[CA TTC] =
SUM(CASE WHEN [LIBELLE] = 'CREDIT CARD' THEN [CA TTC] ELSE 0 END) +
SUM(CASE WHEN [LIBELLE] = 'CHECK' THEN [CA TTC] ELSE 0 END) +
SUM(CASE WHEN [LIBELLE] = 'SPECIES' THEN [CA TTC] ELSE 0 END),
[CREDIT CARD] = SUM(CASE WHEN [LIBELLE] = 'CREDIT CARD' THEN [CA TTC] ELSE 0 END),
[CHECK] = SUM(CASE WHEN [LIBELLE] = 'CHECK' THEN [CA TTC] ELSE 0 END),
[SPECIES] = SUM(CASE WHEN [LIBELLE] = 'SPECIES' THEN [CA TTC] ELSE 0 END)
FROM CTE
GROUP BY [JOUR]

Related

Convert column to row and sum query in different table

i trying to figure to convert sumtchtraffic and totalpayloadGb column in sitetable and sum data totalpayloadGb & sumtchtraffic where BTS_TYPE 2g, 3g and 4g in techtable
i tried like this, but i cant show totalpayloadgb & sumtchtraffic in column [SUM OF] ([sum of] is not in any table in my database)
select * from (select
sum(case when techtable.BTS_TYPE='2G' then sitetable.TotalPayloadGb else 0 end) as [Total 2G],
sum(case when techtable.BTS_TYPE='3G' then sitetable.TotalPayloadGb else 0 end) as [Total 3G],
sum (case when techtable.BTS_TYPE='4G'then sitetable.TotalPayloadGb else 0 end) as [Total 4G]
from sitetable
inner join techtable on sitetable.sitename = techtable.sitename) as t
I want show my data like this:
One way would be to total your results separately, using the same conditional aggregation you have started, and then UNION the results together. Since your first column doesn't exist anywhere else, you'll have to hard-code it into the queries.
SELECT
'TotalPayloadGb' AS SumOf,
sum(CASE WHEN t.BTS_TYPE = '2G' THEN s.TotalPayloadGb ELSE 0 END) AS [Total 2G],
sum(CASE WHEN t.BTS_TYPE = '3G' THEN s.TotalPayloadGb ELSE 0 END) AS [Total 3G],
sum(CASE WHEN t.BTS_TYPE = '4G' THEN s.TotalPayloadGb ELSE 0 END) AS [Total 4G]
FROM sitetable AS s
INNER JOIN techtable AS t
ON s.sitename = t.sitename
UNION
SELECT
'SumTCHTraffic' AS SumOf,
sum(CASE WHEN t.BTS_TYPE = '2G' THEN s.SumTCHTraffic ELSE 0 END) AS [Total 2G],
sum(CASE WHEN t.BTS_TYPE = '3G' THEN s.SumTCHTraffic ELSE 0 END) AS [Total 3G],
sum(CASE WHEN t.BTS_TYPE = '4G' THEN s.SumTCHTraffic ELSE 0 END) AS [Total 4G]
FROM sitetable AS s
INNER JOIN techtable AS t
ON s.sitename = t.sitename;
Depending on what you are trying to do, you could do like this:
SELECT tt.BTS_Type, sum(st.TotalPayloadDb)
FROM SiteTable st
INNER JOIN TechTable as tt on st.sitename = tt.sitename
This will give one row per BTS_Type value.

Combine Table in SQL

I have two tables would like to combine.
I would like the table will automatically add a row for image2 when there are new generalname in image1.
select B.Trsdate, count(B.Billno) As Billno, sum(B.pax) As Pax, sum(B.Grossamount) As GrossAmount, sum(B.discountamount) As Discount, sum(B.taxamount) As Tax, sum(B.servicechargeamount) As SCharge, sum(B.nettamount) As NettAmt, sum(B.rounddiff) As RDiff, sum(B.roundamt) As RoundAmt, sum(B.reversalYN) As RevBillNo, SUM(GD.CASH) AS 'P_CASH', SUM(GD.VISA) AS 'P_VISA', SUM(GD.MASTER) AS 'P_MASTER', SUM(GD.AMEX) AS 'P_Amex', SUM(GD.CityLedger) AS 'P_CityLedger', SUM(GD.OtherPayment) As 'P_Other'
from vpos_eod_bills As B
INNER JOIN
(
SELECT TrsNo,SUM(CASH) as CASH,SUM(Visa) as Visa, SUM(Master) as Master, SUM(Amex) AS Amex, SUM(CityLedger) as CityLedger, SUM(OtherPayment) as OtherPayment, SUM(Total) as Total FROM
(
select TrsNo, GENERALNAME,
(case WHEN(Generalname IN ('CASH'))
THEN
SUM(AMOUNT)
ELSE
0
END) as 'CASH',
(case WHEN(Generalname IN ('VISA'))
THEN
SUM(AMOUNT)
ELSE
0
END) as 'Visa',
(case WHEN(Generalname IN ('MASTER'))
THEN
SUM(AMOUNT)
ELSE
0
END) as 'Master',
(case WHEN(Generalname IN ('AMEX'))
THEN
SUM(AMOUNT)
ELSE
0
END) as 'Amex',
(case WHEN(Generalname = 'City Ledger' OR Generalname = 'CREDIT A/C' OR Generalname = 'BOSS' OR Generalname = 'ENTERTAINMENT')
THEN
SUM(AMOUNT)
ELSE
0
END) as 'CityLedger',
(case WHEN(Generalname not IN ('CASH','Voucher','VISA','MASTER','AMEX','JCB','City Ledger','CREDIT A/C','BOSS','ENTERTAINMENT') and (Generalname not like '%card%') and (Generalname not like '%Coupon%') and (Generalname not like '%GROUPON%') and (Generalname not like '%COURSE%'))
THEN
SUM(AMOUNT)
ELSE
0
END) as 'OtherPayment',
SUM(AMOUNT) as Total
from Vpos_eod_GeneralDetails
where BillType = 'P'
group by TrsNo, GeneralName
) As A
Group By A.trsno
)As GD ON GD.TrsNo = B.TrsNo
where B.PaidStatus = '1' and B.VoidStatus = '0' and (B.trsdate between '20200101' and '20200131')
group by B.trsdate

How do I case sum a column based on a value - 1?

So I have the following 2 columns
,sum(case when Owner_Faculty_Full_Desc = 'Business and Law Faculty' then 1 else 0 end) [Business Current Year]
,sum(case when Owner_Faculty_Full_Desc = 'Business and Law Faculty' AND Apps.Reporting_Year = (Apps.Reporting_Year - 1) then 1 else 0 end) [Business Previous Year]
Lets say that Apps.ReportingYear is 2011, how to I get the second column to sum all values in 2010? I thought my statement would work but it doesn't seem to be.
Here is the entire query
WITH Equiv_day AS (
SELECT Date_Key, Sem1_Equivalent_Day
FROM [AUTDataWarehouse].[dbo].[Dim_Date]
WHERE Full_Date = CONVERT(DATE, GETDATE())
),
Date_list AS (
SELECT dt.Date_Key, dt.Calendar_Year
FROM [AUTDataWarehouse].[dbo].[Dim_Date] AS dt
INNER JOIN Equiv_day AS ed
ON (ed.Sem1_Equivalent_Day - 1) = dt.Sem1_Equivalent_Day
AND dt.Calendar_Year IN (YEAR(GETDATE()), YEAR(GETDATE())-1, YEAR(GETDATE()) - 2, YEAR(GETDATE()) - 3, YEAR(GETDATE()) - 4, YEAR(GETDATE()) - 5)
),
PYTD_Outcome_by_Application AS (
SELECT
se.Reporting_Year,
f.Student_Demographics_Key,
f.Application_Code,
Outcome_Row = Max(f.Application_Row_Num)
FROM AUTDataWarehouse.dbo.Fact_Admission as f
INNER JOIN AUTDataWarehouse.dbo.Dim_Intake as it
ON it.Intake_Key = f.Intake_Key
AND it.Prog_Intake_Type_Desc = 'Intake'
INNER JOIN AUTDataWarehouse.dbo.Dim_Semester as se
ON se.Semester_Key = f.Semester_Key
INNER JOIN AUTDataWarehouse.dbo.Dim_Campus as cp
ON cp.Campus_Key = f.Campus_Key
INNER JOIN Date_list as dates
ON dates.Calendar_Year = se.Reporting_Year
WHERE f.Last_Change_Date_Key < dates.Date_Key
GROUP BY
se.Reporting_Year,
f.Student_Demographics_Key,
f.Application_Code
),
Applications_Count AS (
SELECT
p.Owner_Faculty_Full_Desc,
p.Programme_Full_Desc,
et.Enrolment_Type_Key,
se.Reporting_Year,
sd.Last_Secondary_School_Name [LastSchoolName],
pr.Programme_Key,
Campus = CASE WHEN cp.Campus_Name IN ('South','South Dist') THEN 'South' ELSE 'City / North Shore' END,
se.Semester_Desc,
f.Student_Demographics_Key,
Applicants = COUNT(DISTINCT f.Student_Demographics_Key)
FROM AUTDataWarehouse.dbo.Fact_Admission as f
INNER JOIN AUTDataWarehouse.dbo.Dim_Student_Demographics as sd ON sd.Student_Demographics_Key = f.Student_Demographics_Key
INNER JOIN AUTDataWarehouse.dbo.Dim_Programme as P on P.Programme_Key = f.Programme_Key
INNER JOIN AUTDataWarehouse.dbo.Dim_Intake as it
ON it.Intake_Key = f.Intake_Key
AND it.Prog_Intake_Type_Desc = 'Intake'
INNER JOIN AUTDataWarehouse.dbo.Dim_Enrolment_Type as et
ON et.Enrolment_Type_Key = f.Enrolment_Type_Key
INNER JOIN AUTDataWarehouse.dbo.Dim_Programme as pr
ON pr.Programme_Key = f.Programme_Key
INNER JOIN AUTDataWarehouse.dbo.Dim_Campus as cp
ON cp.Campus_Key = f.Campus_Key
INNER JOIN AUTDataWarehouse.dbo.Dim_Semester as se
ON se.Semester_Key = f.Semester_Key
INNER JOIN Date_list as dates
ON dates.Calendar_Year = se.Reporting_Year
INNER JOIN PYTD_Outcome_by_Application AS pytd
ON pytd.Application_Code = f.Application_Code
AND pytd.Student_Demographics_Key = f.Student_Demographics_Key
AND pytd.Outcome_Row = f.Application_Row_Num
and pytd.Reporting_Year = se.Reporting_Year
AND pytd.Application_Code IS NOT NULL
GROUP BY
sd.Last_Secondary_School_Name,
p.Owner_Faculty_Full_Desc,
p.Programme_Full_Desc,
et.Enrolment_Type_Key,
se.Reporting_Year,
pr.Programme_Key,
CASE WHEN cp.Campus_Name IN ('South','South Dist') THEN 'South' ELSE 'City / North Shore' END,
se.Semester_Desc,
f.Student_Demographics_Key
)
SELECT
CAST(EP.Educational_Provider_Key as varchar(10)) as 'Education Key'
,[LastSchoolName]
,Owner_Faculty_Full_Desc
,Programme_Full_Desc
,Apps.Reporting_Year
,cast(cast(Apps.Reporting_Year as varchar(255)) + '0101' as datetime) as [YearTime]
,sum(case when Owner_Faculty_Full_Desc = 'Business and Law Faculty' then 1 else 0 end) [Business and Law Current Year]
,sum(case when Owner_Faculty_Full_Desc = 'Business and Law Faculty' AND (Apps.Reporting_Year = Apps.Reporting_Year - 1) then 1 else 0 end) [Business and Law Previous Year]
,sum(case when Owner_Faculty_Full_Desc = 'Culture and Society Faculty' then 1 else 0 end) [Culture and Society Current Year]
,sum(case when Owner_Faculty_Full_Desc = 'Culture and Society Faculty' AND Apps.Reporting_Year = 2014 then 1 else 0 end) [Culture and Society Previous Year]
,sum(case when Owner_Faculty_Full_Desc = 'Design & Creative Technologies Faculty'then 1 else 0 end) [Design & Creative TechnologiesCurrent Year]
,sum(case when Owner_Faculty_Full_Desc = 'Design & Creative Technologies Faculty' AND Apps.Reporting_Year = (Apps.Reporting_Year - 1) then 1 else 0 end) [Design & Creative Technologies Previous Year]
,sum(case when Owner_Faculty_Full_Desc = 'Health & Environmental Sciences Faculty'then 1 else 0 end) [Health & Environmental Sciences Current Year]
,sum(case when Owner_Faculty_Full_Desc = 'Health & Environmental Sciences Faculty' AND Apps.Reporting_Year = (Apps.Reporting_Year - 1) then 1 else 0 end) [Health & Environmental Sciences Previous Year]
,sum(case when Owner_Faculty_Full_Desc = 'Te Ara Poutama' then 1 else 0 end) [Te Ara Poutama Current Year]
,sum(case when Owner_Faculty_Full_Desc = 'Te Ara Poutama' AND Apps.Reporting_Year = (Apps.Reporting_Year - 1) then 1 else 0 end) [Te Ara Poutama Previous Year]
,sum(apps.Applicants) [Total Applicants]
FROM Applications_Count as Apps
inner join AUTDataWarehouse.dbo.Dim_Educational_Provider as EP on EP.Provider_Name = [LastSchoolName]
GROUP BY Apps.Reporting_Year, [LastSchoolName], EP.Educational_Provider_Key,Owner_Faculty_Full_Desc
, Programme_Full_Desc
ORDER BY Apps.Reporting_Year, [Total Applicants] DESC
So basically for each programme I want a column for total applicants for the ReportingYear then total applicants for the Reporting Year - 1
Thanks!
Probably easiest to calculate the years separately, then self-join to get the value for the previous year. This is the basic logic you would use, although obviously you will need to make it more complex when you adapt it to the long query above:
;with CTE as (select ReportingYear
, sum(case when [condition] then 1 else 0 end) as ValueCurrYear
from MyTables
group by ReportingYear)
Select a.*, b.ValueCurrYear as ValuePreviousYear
from CTE a
left join CTE b
on a.ReportingYear = b.ReportingYear + 1

Oracle SQL - simplifying the totals column

I have the below issues that I would like to address:
Is there a way to simplify the Total column?
The bottom row reads as null, I would like that to be "Total" as well.
Is it better to ROLLUP the way I have it, ROLLUP((status))? Or this is exactly same as ROLLUP(status)?
Below is my query:
SELECT
status AS "ROW LABELS",
COUNT(case when source = 'INTERNET' THEN 1 end) AS "INTERNET",
COUNT(case when source = 'SALES' THEN 1 end) AS "SALES",
COUNT(case when source = 'REP' THEN 1 end) AS "REP",
COUNT(case when source = 'COM' THEN 1 end) AS "COM",
(COUNT(case when source = 'INTERNET' THEN 1 end) +
COUNT(case when source = 'SALES' THEN 1 end) +
COUNT(case when source = 'REP' THEN 1 end) +
COUNT(case when source = 'COM' THEN 1 end)
) AS Total
FROM
SOMETABLE
GROUP BY ROLLUP((status))
order by 1;
Below is my data:
If by "simplify" you mean "make the calculation more succinct", then yes. The following will work:
COUNT(CASE WHEN source IN ('INTERNET', 'SALES', 'REP', 'COM') THEN 1 END)
Simply use nvl to convert the NULL to a value: NVL(status, 'TOTAL') AS row_labels
ROLLUP( (status) ) is the same as ROLLUP( status )

Get the Sum of a column grouped by another column then grouped into another

I've been trying for a while now to figure this out but my lack of more advanced SQL skills are holding me back.
Executions(TradeDate, Symbol, Side, Price, Under, Account)
TEMP DATA:
2012-06-20, AAPL 120716C00600000, BUY, 3.25, AAPL, XYZ123
2012-06-20, AAPL 120716C00600000, SELL, 3.30, AAPL, XYZ123
2012-06-20, AAPL 120716C00600000, BUY, 3.25, AAPL, XYZ123
2012-06-20, AAPL 120716C00600000, SELL, 3.30, AAPL, XYZ123
2012-06-20, GRPN 120716C00027000, BUY, 2.25, GRPN, XYZ123
2012-06-20, GRPN 120716C00027000, SELL, 2.30, GRPN, XYZ123
2012-06-20, GRPN 120716C00027000, SELL, 2.30, GRPN, XYZ123
2012-06-20, GRPN 120716C00027000, BUY, 2.25, GRPN, XYZ123
-UNDER----Side(Buy)----Side(Sell)
AAPL 6.50 6.60
GRPN 4.50 4.60
As you can see I'm trying to get the SUM of the Price for each Side and then grouped by the Under.
Use GROUP BY to group by Under column and CASE associated with SUM to get the needed results:
SELECT e.Under,
SUM(case when e.Side = 'BUY' them e.Price else 0 end) as 'Side(Buy)',
SUM(case when e.Side = 'SELL' them e.Price else 0 end) as 'Side(Sell)'
FROM Executions e
GROUP BY e.Under
You can use a PIVOT for this. (See SQL Fiddle for Demo)
select *
from
(
select under, price, side
from executions
) x
PIVOT
(
sum(price)
for side in ([BUY], [SELL])
) p
select Symbol, sum(case when side = 'BUY' THEN Price else 0 END) as [Side(Buy)], sum(case when side = 'SELL' THEN Price else 0 END) as [Side(Sell)] group by Symbol
Here's one approach:
SELECT e.under
, SUM(CASE WHEN e.side = 'BUY' THEN e.price ELSE NULL END) AS [Side(Buy)]
, SUM(CASE WHEN e.side = 'SELL' THEN e.price ELSE NULL END) AS [Side(Sell)]
FROM Executions e
GROUP BY e.under
The "trick" here is to use a CASE expression to return the Price only for certain values of side.
(NOTE: As someone will inevitably point out, the ELSE NULL is implicit, and can be omitted.)
This isn't the only approach. But it's a flexible approach that works very well if you also need to also get, for example, a "count" of the rows included in each of the sum, along with a count of all rows. To illustrate this approach being exercised:
SELECT e.under
, SUM(CASE WHEN e.side = 'BUY' THEN e.price ELSE NULL END) AS [SUM_Side(Buy)]
, SUM(CASE WHEN e.side = 'BUY' THEN 1 ELSE 0 END) AS [COUNT_Side(Buy)]
, SUM(CASE WHEN e.side = 'SELL' THEN e.price ELSE NULL END) AS [SUM_Side(Sell)]
, SUM(CASE WHEN e.side = 'SELL' THEN 1 ELSE 0 END) AS [COUNT_Side(Sell)]
, SUM(CASE WHEN e.side IN ('BUY','SELL') THEN 1 ELSE 0 END) AS [COUNT_(Buy+Sell)]
FROM Executions e
GROUP BY e.under
This approach usually has very predictable performance, and it requires that the source dataset be referenced only once (in this case, a simple table reference)
This approach works in nearly every relational database. (Oracle, SQL Server, MySQL, Teradata, DB2, ... )