Transposing data ( calculating monthly sales data) in sql - sql

My data has total 100 rows
Day Item Price Unit
01/01/17 jeans 15 4
01/02/17 shirt 10 3
01/01/17 skirt 20 7
01/04/17 skirt 25 1
02/01/17 jeans 5 4
02/02/17 shirt 15 3
02/01/17 skirt 24 7
03/04/17 skirt 25 5
I want ro represent my data as monthly sale by item in january and february
data should represent as
month jeans skirt shirt total
Jan
Feb
I am getting error in my code
SELECT MONTH,
MAX(CASE WHEN ITEM = 'JEANS' THEN GRANDTOTAL END) GRANDTOTAL,
MAX(CASE WHEN ITEM = 'SHIRT' THEN GRANDTOTAL END) AS GRANDTOTAL,
MAX(CASE WHEN ITEM = 'SKIRT' THEN GRANDTOTAL END) AS GRANDTOTAL,
FROM SALES
GROUP BY MONTH ;
I tried all methods but getting error, please help :)

Sales per item is defined as the sum of price x unit while total sales is the sum of sales for all items.
see demo:
http://sqlfiddle.com/#!9/2a9e8f/1
SELECT date_format(day, '%b') as `month`,
sum(case when item='jeans' then price*unit else 0 end) as jeans,
sum(case when item='shirt' then price*unit else 0 end) as shirts,
sum(case when item='skirt' then price*unit else 0 end) as skirts,
sum(price*unit) as total
FROM myTbl
where month(day) <= 2
GROUP BY date_format(day, '%b')
ORDER BY month(day);
result:
month jeans shirts skirts total
Jan 60 30 165 255
Feb 20 45 168 233

Related

Need to find count of profit and loss and no data using select subquery

I have the following table
Years Months Credit Debit ProfitandLoss Symbol
2019 Jan 10000 2000 1000 P
2019 Aug 8000 1000 -10922 L
2019 May 5000 3000 2000 P
2020 Feb 10000 5000 800 P
2020 Apr 1000 6000 0 N
2020 Oct 2000 1000 2000 P
2021 Jan 6000 8000 -600 L
2021 Mar 2000 3000 1400 P
2021 Nov 2000 2000 0 N
Here I need to calculate total credit, total debit, total profit and loss and total count of profit, total count of loss, total count of nothing in one result table.
I have tried this but cannot get CountOfProfit, CountOfLoss and CountNothing according to years.
select Years,
SUM(credit) as [Total Credit],
SUM(debit) as totaldebit,
COUNT(Symbol) as totalcredit,
(select COUNT(Symbol) from Yearly where Symbol='P') as CountofProfit,
(select COUNT(Symbol) from Yearly where Symbol='L') as CountofLoss,
(select COUNT(Symbol) from Yearly where Symbol='N')as CountNothing
from Yearly
group by Years
My result table should be like
Years TotalCredit TotalDebit TotalProfitandLoss CountOfProfit CountofLoss CountofNothing
2019 23000 7000 -7022 2 1 0
2020 13000 12000 2800 2 0 1
2021 10000 13000 800 1 1 1
You need use conditional aggregation. This is achieved with a CASE expression:
SELECT Years,
SUM(Credit) AS TotalCredit,
SUM(Debit) AS TotalDebit,
SUM(ProfitandLoss) AS TotalProfitAndLoss,
COUNT(CASE Symbol WHEN 'P' THEN 1 END) AS Profits,
COUNT(CASE Symbol WHEN 'L' THEN 1 END) AS Losses,
COUNT(CASE Symbol WHEN 'N' THEN 1 END) AS Nothings
FROM (VALUES(2019,'Jan',10000,2000, 1000 ,'P'),
(2019,'Aug',8000 ,1000,-10922,'L'),
(2019,'May',5000 ,3000, 2000 ,'P'),
(2020,'Feb',10000,5000, 800 ,'P'),
(2020,'Apr',1000 ,6000, 0 ,'N'),
(2020,'Oct',2000 ,1000, 2000 ,'P'),
(2021,'Jan',6000 ,8000, -600 ,'L'),
(2021,'Mar',2000 ,3000, 1400 ,'P'),
(2021,'Nov',2000 ,2000, 0 ,'N'))V(Years,Months,Credit,Debit,ProfitandLoss,Symbol)
GROUP BY Years
ORDER BY Years;

Include "0" results in COUNT(*) aggregate

Good morning, I've searched in the forum one doubt that I have but the results that I've seen didn't give me a solution.
I have two tables.
CARS:
Id Model
1 Seat
2 Audi
3 Mercedes
4 Ford
BREAKDOWNS:
IdBd Description Date Price IdCar
1 Engine 01/01/2020 500 € 3
2 Battery 05/01/2020 0 € 1
3 Wheel's change 10/02/2020 110,25 € 4
4 Electronic system 15/03/2020 100 € 2
5 Brake failure 20/05/2020 0 € 4
6 Engine 25/05/2020 400 € 1
I wanna make a query that shows the number of breakdowns by month with 0€ of cost.
I have this query:
SELECT Year(breakdowns.[Date]) AS YEAR, StrConv(MonthName(Month(breakdowns.[Date])),3) AS MONTH, Count(*) AS [BREAKDOWNS]
FROM cars LEFT JOIN breakdowns ON (cars.Id = breakdowns.IdCar AND breakdowns.[Price]=0)
GROUP BY breakdowns.[Price], Year(breakdowns.[Date]), Month(breakdowns.[Date]), MonthName(Month(breakdowns.[Date]))
HAVING ((Year([breakdowns].[Date]))=[Insert a year:])
ORDER BY Year(breakdowns.[Date]), Month(breakdowns.[Date]);
And the result is (if I put year '2020'):
YEAR MONTH BREAKDOWNS
2020 January 1
2020 May 1
And I want:
YEAR MONTH BREAKDOWNS
2020 January 1
2020 February 0
2020 March 0
2020 May 1
Thanks!
The HAVING condition should be in WHERE (otherwise it changes the Outer to an Inner join). But as long as you don't use columns from cars there's no need to join it.
To get rows for months without a zero price you should switch to conditional aggregation (Access doesn't support Standard SQL CASE, but IIF?).
SELECT Year(breakdowns.[Date]) AS YEAR,
StrConv(MonthName(Month(breakdowns.[Date])),3) AS MONTH,
SUM(CASE WHEN breakdowns.[Price]=0 THEN 1 ELSE 0 END) AS [BREAKDOWNS]
FROM breakdowns
JOIN cars
ON (cars.Id = breakdowns.IdCar)
WHERE ((Year([breakdowns].[Date]))=[Insert a year:])
GROUP BY breakdowns.[Price], Year(breakdowns.[Date]), Month(breakdowns.[Date]), MonthName(Month(breakdowns.[Date]))
ORDER BY Year(breakdowns.[Date]), Month(breakdowns.[Date]

Summary with breakdown of dates by dayrange

Here is raw table I have list of ids with dates and counts. I need to pivot counts and break down date current date getdate() to date on the table broken out by 0-5 days , 10-15 ....
Type Date Volume
-------- ----- ------
primary mar 10,2019 1
Sub mar 8,2019 2
Pending mar 13,2019 3
XX mar 4,2019 5
What I want is, to show the result something like this:
TYPE 0-5 Days 5-10 Days 11-15 Days 16-20 Days 21-30 Days Total
primary 1 4 1 6 1 13
sub 3 5 5 7 0 20
pending 1 1 1 1 1 5
5 10 7 14 2 38
I assume you're looking for a conditional sum of the volumes that compares the date with the current date. And with a rollup.
Then something like this :
SELECT Type,
SUM(CASE WHEN DATEDIFF(day,[Date],GetDate()) BETWEEN 0 AND 5 THEN Volume ELSE 0 END) AS [0-5 Days],
SUM(CASE WHEN DATEDIFF(day,[Date],GetDate()) BETWEEN 6 AND 10 THEN Volume ELSE 0 END) AS [6-10 Days],
SUM(CASE WHEN DATEDIFF(day,[Date],GetDate()) BETWEEN 11 AND 15 THEN Volume ELSE 0 END) AS [11-15 Days],
SUM(CASE WHEN DATEDIFF(day,[Date],GetDate()) BETWEEN 16 AND 20 THEN Volume ELSE 0 END) AS [16-20 Days],
SUM(CASE WHEN DATEDIFF(day,[Date],GetDate()) BETWEEN 21 AND 30 THEN Volume ELSE 0 END) AS [21-30 Days],
SUM(Volume) AS Total
FROM yourtable
WHERE [Date] >= CAST(GetDate()-30 AS DATE)
GROUP BY Type WITH ROLLUP

Distinct count for entire dataset, grouped by month

I am dealing with a sales order table (ORDER) that looks roughly like this (updated 2018/12/20 to be closer to my actual data set):
SOID SOLINEID INVOICEDATE SALESAMOUNT AC
5 1 2018-11-30 100.00 01
5 2 2018-12-05 50.00 02
4 1 2018-12-12 25.00 17
3 1 2017-12-31 75.00 03
3 2 2018-01-03 25.00 05
2 1 2017-11-25 100.00 17
2 2 2017-11-27 35.00 03
1 1 2017-11-20 15.00 08
1 2 2018-03-15 30.00 17
1 3 2018-04-03 200.00 05
I'm able to calculate the average sales by SOID and SOLINEID:
SELECT SUM(SALESAMOUNT) / COUNT(DISTINCT SOID) AS 'Total Sales per Order ($)',
SUM(SALESAMOUNT) / COUNT(SOLINEID) AS 'Total Sales per Line ($)'
FROM ORDER
This seems to provide a perfectly good answer, but I was then given an additional constraint, that this count be done by year and month. I thought I could simply add
GROUP BY YEAR(INVOICEDATE), MONTH(MONTH)
But this aggregates the SOID and then performs the COUNT(DISTINCT SOID). This becomes a problem with SOIDs that appears across multiple months, which is fairly common since we invoice upon shipment.
I want to get something like this:
Year Month Total Sales Per Order Total Sales Per Line
2018 11 0.00
The sore thumb sticking out is that I need some way of defining in which month and year an SOID will be aggregated if it spans across multiple ones; for that purpose, I'd use MAX(INVOICEDATE).
From there, however, I'm just not sure how to tackle this. WITH? A subquery? Something else? I would appreciate any help, even if it's just pointing in the right direction.
You should select Year() and month() for invocedate and group by
SELECT YEAR(INVOICEDATE) year
, MONTH(INVOICEDATE) month
, SUM(SALESAMOUNT) / COUNT(DISTINCT SOID) AS 'Total Sales per Order ($)'
, SUM(SALESAMOUNT) / COUNT(SOLINEID) AS 'Total Sales per Line ($)'
FROM ORDER
GROUP BY YEAR(INVOICEDATE), MONTH(INVOICEDATE)
Here are the results, but the data sample does not have enuf rows to show Months...
SELECT
mDateYYYY,
mDateMM,
SUM(SALESAMOUNT) / COUNT(DISTINCT t1.SOID) AS 'Total Sales per Order ($)',
SUM(SALESAMOUNT) / COUNT(SOLINEID) AS 'Total Sales per Line ($)'
FROM DCORDER as t1
left join
(Select
SOID
,Year(max(INVOICEDATE)) as mDateYYYY
,Month(max(INVOICEDATE)) as mDateMM
From DCOrder
Group By SOID
) as t2
On t1.SOID = t2.SOID
Group by mDateYYYY, mDateMM
mDateYYYY mDateMM Total Sales per Order ($) Total Sales per Line ($)
2018 12 87.50 58.33
I have used new SQL still MAX(INVOICEDATE)(not above), with new 12/20 data, and excluded AC=17.
YYYY MM Total Sales per Order ($) Total Sales per Line ($)
2017 11 35.00 35.00
2018 1 100.00 50.00
2018 4 215.00 107.50
2018 12 150.00 75.00

SSRS REPORT SQL

I have data as below
Year Period Country STATUS COST1 COST2 TOTAL COST
2019 1 Australia PERM 100 200 300
2019 2 NZ PERM 200 200 400
2019 3 ASIA TEMP 400 200 600
2019 4 NZ TEMP 500 200 700
I like to show in the SSRS report
I need period on COLUMN and STATUS in ROWS like below and total cost in data section
Period
1 2 3 4
+PERM TOTAL COST
+TEMP
And when end user toggle on + it will show more detail. But otherwise just like that.
Year Country COST1 COST2 TOTAL COST
PERM 2019 1 Australia 100 200 300
2019 2 NZ 200 200 400
TEMP 2019 3 ASIA 400 200 600
2019 4 NZ 500 200 700
thanks in advance
You seem to want conditional aggregation:
select status,
sum(case when period = 1 then total_cost else 0 end) as total_cost_1,
sum(case when period = 2 then total_cost else 0 end) as total_cost_2,
sum(case when period = 3 then total_cost else 0 end) as total_cost_3,
sum(case when period = 4 then total_cost else 0 end) as total_cost_4
from t
group by status;
With a Matrix in SSRS you can set the row groups to be based on the Period and Status without having to add an additional dataset.
Use Period for the Column Grouping so the field will expand to 4 columns based on the Period values.
Result:
This way you can have the detail below in the same table and hide it until the user toggles it.