SQL query for multiple where clause - sql

I have a table named tbl_transactions with columns
Category (string)
for_month (string)
Vehicle_No (string)
amount (float)
As shown below in the
.
Is it possible to get the total amount for each month and the result should be category wise something like

You can use the conditional aggregation as follows:
SELECT CATEGORY,
SUM(CASE WHEN FOR_MONTH = 'April' THEN AMOUNT END) AS APRIL_AMOUNT,
SUM(CASE WHEN FOR_MONTH = 'May' THEN AMOUNT END) AS MAY_AMOUNT,
SUM(CASE WHEN FOR_MONTH = 'June' THEN AMOUNT END) AS JUNE_AMOUNT
FROM YOUR_tABLE T
WHERE FOR_MONTH IN ('April', 'May', 'June')
GROUP BY CATEGORY

Using PIVOT
DECLARE #t TABLE(Cat VARCHAR(MAX), Mon VARCHAR(MAX),Amt INT)
INSERT INTO #T VALUES('Registration','April',850),
('Registration','April',450),
('Registration','April',295)
SELECT Cat, [April] AS [Total Amt in Apr],
[May] AS [Total Amt in May],
[June] AS [Total Amt in June]FROM
(
SELECT
Cat,
Mon,
Amt
FROM
#T
) t
PIVOT(
SUM(Amt)
FOR Mon IN (
[April],
[May],
[June]
)
) AS pivot_table;
Results:
Cat Total Amt in Apr Total Amt in May Total Amt in June
Registration 1595 NULL NULL

Related

T-SQL: Rows to Columns

I am a SQL beginner, so can anyone please help me with this?
I have a table like this
YearMonth | Customer | Currency | BusinessType | Amount
04-2020 | 123 | EUR | Budget | 500
04-2020 | 123 | EUR | Forecast | 300
04-2020 | 123 | EUR | Sales | 700
And now I need it like:
YearMonth | Customer | Currency | Amount Budget | Amount Forecast | Amount Sales
04-2020 | 123 | EUR | 500 | 300 | 700
Is something like this possible?
Thanks in advance for your help!
Use conditional aggregation:
select yearmonth, customer, currency,
sum(case when businesstype = 'Budget' then amount end) as budget,
sum(case when businesstype = 'Forecast' then amount end) as forecast,
sum(case when businesstype = 'Sales' then amount end) as sales
from t
group by yearmonth, customer, currency;
You can do aggregation :
select yearmonth, customer, currency,
sum(case when businesstype = 'budget' then amount else 0 end),
sum(case when businesstype = 'Forecast' then amount else 0 end),
sum(case when businesstype = 'Sales' then amount else 0 end)
from table t
group by yearmonth, customer, currency;
Also, you may want to add an "Other" to capture any new Business Types:
select yearmonth, customer, currency,
sum(case when businesstype = 'Budget' then amount end) as budget,
sum(case when businesstype = 'Forecast' then amount end) as forecast,
sum(case when businesstype = 'Sales' then amount end) as sales,
sum(case when businesstype not in ('Budget', 'Forecast', 'Sales') then amount end) as other
from t
group by yearmonth, customer, currency;
This type of requirements are usually resolved using T-SQL PIVOT relational operation (https://learn.microsoft.com/en-us/sql/t-sql/queries/from-using-pivot-and-unpivot?view=sql-server-ver15). For the above example I used the following query to achieve this:
-- Create a temporary table to store the data.
IF (OBJECT_ID('tempdb..##temp2') IS NOT NULL) DROP TABLE ##temp2
CREATE TABLE ##temp2 (Id int IDENTITY (1,1) PRIMARY KEY, YearMonth varchar(100), Customer int, Currency varchar(100), BusinessType varchar(100), Amount int)
INSERT ##temp2
VALUES
('04-2020', 123,'EUR','Sales', 700),
('04-2020', 123,'EUR','Budget', 500),
('04-2020', 123,'EUR','Forecast', 300)
-- Using PIVOT allows you to move rows into columns
SELECT pivot_table.YearMonth,
pivot_table.Customer,
pivot_table.Currency,
[Amount Forecast] = pivot_table.Forecast,
[Amount Budget] = pivot_table.Budget,
[Amount Sales] = pivot_table.Sales
FROM
(
SELECT YearMonth,
Customer,
Currency,
BusinessType,
Amount
FROM ##temp2
) t
PIVOT
(
SUM(Amount)
FOR BusinessType IN ([Sales], [Budget], [Forecast])
) AS pivot_table;

My Sql PIVOT Query Is Not Working As Intended

I'm using the following SQL query to return a table with 4 columns Year, Month, Quantity Sold, Stock_Code,
SELECT yr, mon, sum(Quantity) as Quantity, STOCK_CODE
FROM [All Stock Purchased]
group by yr, mon, stock_code
order by yr, mon, stock_code
This is an example of some of the data BUT I have about 3000 Stock_Codes and approx 40 x yr/mon combinations.
yr mon Quantity STOCK_CODE
2015 4 42 100105
2015 4 220 100135
2015 4 1 100237
2015 4 2 100252
2015 4 1 100277
I want to pivot this into a table which has a row for each SKU and columns for every Year/Month combination.
I have never used Pivot before so have done some research and have created a SQL query that I believe should work.
select * from
(SELECT yr,
mon, Quantity,
STOCK_CODE
FROM [All Stock Purchased]) AS BaseData
pivot (
sum(Quantity)
For Stock_Code
in ([4 2015],[5 2015] ...........
) as PivotTable
This query returns a table with Yr as col1, Mon as col2 and then 4 2015 etc as subsequent columns. Whereas I want col1 to be Stock_Code and col2 to show the quantity of that stock code sold in 4 2015.
Would really like to understand what is wrong with my code above please.
The following query using dynamic PIVOT should do what you want:
CREATE TABLE #temp (Yr INT,Mnt INT,Quantity INT, Stock_Code INT)
INSERT INTO #temp VALUES
(2015,4,42,100105),
(2015,4,100,100105),
(2015,5,220,100135),
(2015,4,1,100237),
(2015,4,2,100252),
(2015,7,1,100277)
DECLARE #pvt NVARCHAR(MAX) = '';
SET #pvt = STUFF(
(SELECT DISTINCT N', ' + QUOTENAME(CONVERT(VARCHAR(10),Mnt) +' '+ CONVERT(VARCHAR(10),Yr)) FROM #temp FOR XML PATH('')),1,2,N'');
EXEC (N'
SELECT pvt.* FROM (
SELECT Stock_Code
,CONVERT(VARCHAR(10),Mnt) +'' ''+ CONVERT(VARCHAR(10),Yr) AS [Tag]
,Quantity
FROM #temp )a
PIVOT (SUM(Quantity) FOR [Tag] IN ('+#pvt+')) pvt');
Result is as below,
Stock_Code 4 2015 5 2015 7 2015
100105 142 NULL NULL
100135 NULL 220 NULL
100237 1 NULL NULL
100252 2 NULL NULL
100277 NULL NULL 1
You can achieve this without using pivoting.
SELECT P.`STOCK_CODE`,
SUM(
CASE
WHEN P.`yr`=2015 AND P.`mon` = '1'
THEN P.`Quantity`
ELSE 0
END
) AS '1 2015',
SUM(
CASE
WHEN P.`yr`=2015 AND P.`mon` = '2'
THEN P.`Quantity`
ELSE 0
END
) AS '2 2015',
SUM(
CASE
WHEN P.`yr`=2015 AND P.`mon` = '3'
THEN P.`Quantity`
ELSE 0
END
) AS '3 2015',
FROM [All Stock Purchased] P
GROUP BY P.`STOCK_CODE`;

Pivoting unique users for each month, each year

I'm learning about PIVOT function and I want to try it in my DB, in the table DDOT I have events (rows) made by users during X month Y year in the YYYYMM format.
id_ev iddate id_user ...
------------------------
1 201901 321
2 201902 654
3 201903 987
4 201901 321
5 201903 987
I'm basing my query on the MS Documentation and I'm not getting errors but I'm not able to fill it with the SUM of those unique events (users). In simple words I want to know how many users (unique) checked up each month (x axis) in the year (y axis). However, I'm getting NULL as result
YYYY jan feb mar
----------------------------
2019 NULL NULL NULL
I'm expecting a full table with what I mentionted before.
YYYY jan feb mar
----------------------------
2019 2 1 1
In the code I've tried with different aggregate functions but this block is the closest to a result from SQL.
CREATE TABLE ddot
(
id_ev int NOT NULL ,
iddate int NOT NULL ,
id_user int NOT NULL
);
INSERT INTO DDOT
(
[id_ev], [iddate], [id_user]
)
VALUES
(
1, 201901, 321
),
(
2, 201902, 654
),
(
3, 201903, 987
),
(
4, 201901, 321
),
(
5, 201903, 987
)
GO
SELECT *
FROM (
SELECT COUNT(DISTINCT id_user) [TOT],
DATENAME(YEAR, CAST(iddate+'01' AS DATETIME)) [YYYY], --concat iddate 01 to get full date
DATENAME(MONTH, CAST(iddate+'01' AS DATETIME)) [MMM]
FROM DDOT
GROUP BY DATENAME(YEAR, CAST(iddate+'01' AS DATETIME)),
DATENAME(MONTH, CAST(iddate+'01' AS DATETIME))
) AS DOT_COUNT
PIVOT(
SUM([TOT])
FOR MMM IN (jan, feb, mar)
) AS PVT
Ideally you should be using an actual date in the iddate column, and not a string (number?). We can workaround this using the string functions:
SELECT
CONVERT(varchar(4), LEFT(iddate, 4)) AS YYYY,
COUNT(CASE WHEN CONVERT(varchar(2), RIGHT(iddate, 2)) = '01' THEN 1 END) AS jan,
COUNT(CASE WHEN CONVERT(varchar(2), RIGHT(iddate, 2)) = '02' THEN 1 END) AS feb,
COUNT(CASE WHEN CONVERT(varchar(2), RIGHT(iddate, 2)) = '03' THEN 1 END) AS mar,
...
FROM DDOT
GROUP BY
CONVERT(varchar(4), LEFT(iddate, 4));
Note that if the iddate column already be text, then we can remove all the ugly calls to CONVERT above:
SELECT
LEFT(iddate, 4) AS YYYY,
COUNT(CASE WHEN RIGHT(iddate, 2) = '01' THEN 1 END) AS jan,
COUNT(CASE WHEN RIGHT(iddate, 2) = '02' THEN 1 END) AS feb,
COUNT(CASE WHEN RIGHT(iddate, 2) = '03' THEN 1 END) AS mar,
...
FROM DDOT
GROUP BY
LEFT(iddate, 4);

SQL Pivot Table from query

How can I convert this query to pivot
select
branch,
months,
[Parts Revenue Budget]
from #Temp1
Result
Desired Output
You can use conditional aggregation :
SELECT t.branch,
SUM(CASE WHEN t.months = 'JAN' THEN t.[Parts Revenue Budget] ELSE 0 END) as JAN,
SUM(CASE WHEN t.months = 'FEB,' THEN t.[Parts Revenue Budget] ELSE 0 END) as FEB
... As many as you need
SUM(t.[Parts Revenue Budget]) as grandtotal
FROM #Temp1
GROUP BY t.branch
UNION ALL
SELECT 'Grand Total',
SUM(CASE WHEN t.months = 'JAN' THEN t.[Parts Revenue Budget] ELSE 0 END) as JAN,
SUM(CASE WHEN t.months = 'FEB' THEN t.[Parts Revenue Budget] ELSE 0 END) as FEB,
... As many as you need
SUM(t.[Parts Revenue Budget]) as grandtotal
FROM #Temp1 t
SELECT BRANCH,
SUM(CASE WHEN MONTHS = 'JAN' THEN PARTSREVENUEBUDJET END) AS [JAN],
SUM(CASE WHEN MONTHS = 'FEB' THEN PARTSREVENUEBUDJET END) AS [FEB],
SUM(CASE WHEN MONTHS = 'MAR' THEN PARTSREVENUEBUDJET END) AS [MARCH],
SUM(CASE WHEN MONTHS = 'APR' THEN PARTSREVENUEBUDJET END) AS [APR],
SUM(CASE WHEN PONITS = 'MAY' THEN PARTSREVENUEBUDJET END) AS [MAY],
SUM(CASE WHEN MONTHS = 'JUNE' THEN PARTSREVENUEBUDJET END) AS [JUNE],
SUM(CASE WHEN MONTHS = 'JULY' THEN PARTSREVENUEBUDJET END) AS [JULY],
SUM(CASE WHEN MONTHS = 'AUG' THEN PARTSREVENUEBUDJET END) AS [AUG],
SUM(CASE WHEN MONTHS = 'SEP' THEN PARTSREVENUEBUDJET END) AS [SEP],
SUM(CASE WHEN MONTHS = 'OCT' THEN PARTSREVENUEBUDJET END) AS [OCT],
SUM(CASE WHEN MONTHS = 'NOV' THEN PARTSREVENUEBUDJET END) AS [NOV],
SUM(CASE WHEN MONTHS = 'NOV' THEN PARTSREVENUEBUDJET END) AS [DEC],
SUM(PARTSREVENUEBUDJET) AS 'GRANDTOTAL'
FROM TABLE
GROUP BY BRANCH
2)
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(months)
from #TEMP1
group by months
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT branch,' + #cols + ',tiot from
(
select *,sum(BUDGET)over(partition by branch) as tiot
from #TEMP1
) x
pivot
(
sum(BUDGET)
for months in (' + #cols + ')
) p '
exec(#query);
I tried as follows:
CREATE TABLE #TEMP1(BRANCH VARCHAR(100),MONTHS VARCHAR(100),BUDGET varchar(100))
INSERT INTO #TEMP1 VALUES ('CPD','APR','801375')
INSERT INTO #TEMP1 VALUES ('Sabzi Mandi','APR','1033697')
INSERT INTO #TEMP1 VALUES ('DHA','APR','2119835')
INSERT INTO #TEMP1 VALUES ('Quidabad','APR','2100042')
INSERT INTO #TEMP1 VALUES ('Sukkar','AUG','44377320')
INSERT INTO #TEMP1 VALUES ('Baghbanpura','AUG','2726114')
INSERT INTO #TEMP1 VALUES ('Multan','AUG','6068565')
select *,coalesce(CAST(AUG AS NUMERIC(10,2)),0)+coalesce(CAST(apr AS NUMERIC(10,2)),0) as 'grand total'
from
(select branch , months ,budget from #temp1) as s
pivot
(MAX(BUDGET) for months in (APR,AUG)) AS PVT
CREATE TABLE TEMP1(BRANCH VARCHAR(100),MONTHS VARCHAR(100),BUDGET FLOAT(126));
INSERT INTO TEMP1 VALUES ('ABC','AUG','1000');
INSERT INTO TEMP1 VALUES ('PQR','APR','2000');
INSERT INTO TEMP1 VALUES ('XYZ','AUG','1000');
SELECT
BRANCH,
APR,
AUG,
(NVL(APR,'0')+NVL(AUG,'0')) AS GRANDTOTAL
FROM
(SELECT
*
FROM
(
SELECT
BRANCH,
MONTHS,
BUDGET
FROM
TEMP1
)
pivot ( MIN(BUDGET) FOR MONTHS IN ('APR' AS APR,'AUG' AS AUG)))
UNION ALL
SELECT 'GRAND TOTAL' AS BRANCH,SUM(APR) AS APR, SUM(AUG) AS AUG, SUM(GRANDTOTAL) AS GRANDTOTAL
FROM
(SELECT
BRANCH,
APR,
AUG,
(NVL(APR,'0')+NVL(AUG,'0')) AS GRANDTOTAL
FROM
(SELECT
*
FROM
(
SELECT
BRANCH,
MONTHS,
BUDGET
FROM
TEMP1
)
pivot ( MIN(BUDGET) FOR MONTHS IN ('APR' AS APR,'AUG' AS AUG) )));

Without PIVOT, display data where GROUP BY column are the column names

I have data that looks like the following:
Name Date Hr Min Amt
Joe 20150320 08 00 5
Joe 20150320 08 15 3
Carl 20150320 09 30 1
Carl 20150320 09 45 2
Ray 20150320 13 00 8
Ray 20150320 13 30 6
A simple GROUP BY [Name], [Date], [Hr] would display the total by hour for each salesman.
Without using PIVOT or dynamic sql, how can I display this data where the hours are the columns? With PIVOT I would need to detail each hour, so if the data above were the only data, there would be 3 columns with data (8, 9, 13), and 21 empty columns.
The reason I want to do this is because I would like to create an SSRS report where the columns are the hours. Unfortunately, I can't use a matrix because I can't sort by the column detail (ie. click on "8" and display from smallest to largest); I've already confirmed this limitation with an MS expert.
So any help is appreciated. We have Sql Server 2008 R2.
Thanks.
Select Name
,[Date]
,SUM(Case When Hr = '00' THEN Amt END) [00]
,SUM(Case When Hr = '01' THEN Amt END) [01]
,SUM(Case When Hr = '02' THEN Amt END) [02]
,SUM(Case When Hr = '03' THEN Amt END) [03]
,SUM(Case When Hr = '04' THEN Amt END) [04]
,SUM(Case When Hr = '05' THEN Amt END) [05]
,SUM(Case When Hr = '06' THEN Amt END) [06]
,SUM(Case When Hr = '07' THEN Amt END) [07]
,SUM(Case When Hr = '08' THEN Amt END) [08]
,SUM(Case When Hr = '09' THEN Amt END) [09]
,SUM(Case When Hr = '10' THEN Amt END) [10]
,SUM(Case When Hr = '11' THEN Amt END) [11]
,SUM(Case When Hr = '12' THEN Amt END) [12]
,SUM(Case When Hr = '13' THEN Amt END) [13]
,SUM(Case When Hr = '14' THEN Amt END) [14]
,SUM(Case When Hr = '15' THEN Amt END) [15]
,SUM(Case When Hr = '16' THEN Amt END) [16]
,SUM(Case When Hr = '17' THEN Amt END) [17]
,SUM(Case When Hr = '18' THEN Amt END) [18]
,SUM(Case When Hr = '19' THEN Amt END) [19]
,SUM(Case When Hr = '20' THEN Amt END) [20]
,SUM(Case When Hr = '21' THEN Amt END) [21]
,SUM(Case When Hr = '22' THEN Amt END) [22]
,SUM(Case When Hr = '23' THEN Amt END) [23]
From TablenName
Group By Name ,[Date]
something like this work?? put your key fields into temp tables dont join them so you create a possibility for everything then sub query your amt in.
select * into #Temp1 from (
select '01' as 'Pivot_Hour'
union all
select '02' as 'Pivot_Hour'
union all
select '03' as 'Pivot_Hour'
union all
select '04' as 'Pivot_Hour'
union all
select '05' as 'Pivot_Hour'
--Put all 24 hours in....
)
x
select * into #Temp2 from (
select 'Carl' as 'User'
union all
select 'Joe' as 'User'
union all
select 'Ray' as 'User'
union all
select 'Dave' as 'User'
union all
select 'Seve' as 'User'
---Could select distinct from your data...
)
x
Select * into #Temp3 from (
select '20150321' as 'Date'
union all
select '20150322' as 'Date'
union all
select '20150323' as 'Date'
union all
select '20150324' as 'Date'
union all
select '20150325' as 'Date'
---Could select distinct from your data...
)
x
select *
,(select sum(yrd.amt) from Yourdata Yrd
where yrd.Name = t2.User
and yrd.date = t3.date
and yrd.Hr = t1.Pivot_Hour)Amt
from #Temp1 t1,#Temp2 t2,#Temp3 t3
drop table #Temp1
drop table #Temp2
drop table #Temp3