I need to group sum in from previous period in SQL. Here's my data from simplified customer (customer A, B, and C)
Customer Year Month Order
A 2019 5 10
A 2019 4 5
A 2019 3 3
A 2019 2 1
A 2018 12 3
B 2019 5 1
B 2019 4 2
B 2019 3 1
C 2019 5 2
C 2019 4 1
C 2019 2 1
C 2019 1 3
Expected output is sum Order for previous period
For example, Expected output in first row is 12, because it sum in previous period (7 + 4 + 3 + 0) in customer A.
Another example, Expected output in second row is 7 because it sum in previous period (4 + 3 + 0) in customer A. So, table below is the expected output from table above
Customer Year Month Order Output
A 2019 5 10 12
A 2019 4 5 7
A 2019 3 3 4
A 2019 2 1 3
A 2018 12 3 0
B 2019 5 1 3
B 2019 4 2 1
B 2019 3 1 0
C 2019 5 2 5
C 2019 4 1 4
C 2019 2 1 3
C 2019 1 3 0
I need to do this in SQL
First of all, i would change the name of your columns (year, month and order are mysql reserved words or functions). You could do it with a subquery like this:
select customer,
`year`,
`month`,
`order`,
(select sum(output)
from yourtable b
where a.customer=b.customer and (a.year>b.year or (a.year=b.year and a.month>b.month)))
from yourtable a
What you do is you get every row and the last column is the sum of output for all other columns with the same customer and have year lower than the year in your customer or if the year is the same, the month is lower
In MySQL 8+, you should use window functions:
select t.*,
sum(output) over (partition by customer order by year, month)
from t;
Note only is this more concise, but it should have better performance as well.
This can be achieved by Window Functions. Below link provides the example
LAG([,offset[, default_value]]) OVER (
PARTITION BY expr,...
ORDER BY expr [ASC|DESC],...
)
http://www.mysqltutorial.org/mysql-window-functions/mysql-lag-function/
Related
I need to add a new column to my table that will have the difference between sum of revenue of a new quarter over the last one.
My data looks like this:
Website Year Quarter Revenue
cosmo.com 2019 4 10
cosmo.com 2020 1 15
cosmo.com 2020 2 5
fashion.com 2019 4 10
fashion.com 2020 1 5
fashion.com 2020 2 20
The desired output is:
Website Year Quarter Revenue Difference
cosmo.com 2019 4 10 +5
cosmo.com 2020 1 15 +5
cosmo.com 2020 2 5 -10
fashion.com 2019 4 10 +10
fashion.com 2020 1 5 -5
fashion.com 2020 2 20 +15
I have tried to see the yearly difference, to begin with, but got a syntax error
select *,
`Revenue` - lag(`Revenue`) over(order by `Year`) as difference
from table`
From what I can tell, you want the difference from the previous quarter, not year. That would be:
select t.*,
(t.Revenue - lag(t.Revenue) over (partition by website order by Year, quarter)) as difference
from table t;
Note the use of partition by for the website.
I have an SQL table that contains order data by date. I'm trying to combine the data across years in 4 weeks buckets so that I can compare year on year periods. Luckily the table contains year and week number columns so that I can sum the data to show order totals by week number, for example:
By using SELECT order_year, order_week_number, sum(order_total) from f2l4d1a2ta_237_floodlight_order_data_v1 group by order_week_number ORDER BY order_week_number, order_year
I get:
order_year order_week_number sum(order_total)
2017 1 96.40879041
2017 2 33.34092216
2017 3 97.79772267
2017 4 28.05668819
2017 5 75.79034382
2017 6 41.59171513
2017 7 3.754344347
2017 8 66.27940579
2016 1 65.81290635
2016 2 71.17703765
2016 3 65.95184929
2016 4 90.42108213
2016 5 44.32837015
2016 6 19.9644766
2016 7 53.46359297
2016 8 7.059479081
However what I'm really after is to see the order total for the 4 week period in the year, i.e.
order_year 4 week period sum(order_total)
2017 1 255.6041234
2017 2 187.4158091
2016 1 293.3628754
2016 2 124.8159188
Does anyone know how to group data with SQL in this way?
Thanks,
Matt
Add 3 to the week number then integer divide by 4 (whole number result)
Eg (1+3) DIV 4 = 1, (4+3) DIV 4 = 1
So GROUP BY (weekno + 3) DIV 4
I am trying to find a MySQL query that will display the number of occurrences of an ID value within a year.
Table:
a_id year
---- ----
1 2010
1 2011
1 2012
1 2012
1 2013
1 2014
1 2015
2 2010
2 2011
2 2013
2 2014
2 2014
2 2015
3 2010
3 2010
3 2011
Expected output:
a_id year occurrences
---- ----- -----------
1 2010 1
1 2011 1
1 2012 2
1 2013 1
1 2014 1
1 2015 1
2 2010 1
2 2011 1
2 2013 1
2 2014 2
2 2015 1
3 2010 2
3 2011 1
I'm trying with the something along the lines of following sql query, but it gives me nothing like the expected output. It's the 3rd column im struggling with.
SELECT a__id, year, count(distinct a_id) as occurrences
FROM table1
GROUP by year
ORDER by a_id
How can i create that 3rd column?
Scince you are grouping by a_id and year you of course get only 1 distinct value for group. Simply change count(distinct a_id) to count(*).
For example you get group:
1 2012
1 2012
Notice in this group distinct a_id values is 1. But you want count of all rows in group. With distinct you will get 1 as occurence in all groups.
EDIT:
Ok, I have missed that you are grouping only by year, so you should group by a_id also. The rest of the answer stays as is. So you end up with:
SELECT a__id, year, count(*) as occurrences
FROM table1
GROUP by a__id, year
SELECT a__id, year, count(*) as occurrences
FROM table1
GROUP by a__id, year
Using the following will get you what you are looking for.
SELECT a_id, year, count(*)
FROM table1
GROUP BY a_id, year
ORDER BY a_id, year
Although, in previous versions, ORDER BY may have been guaranteed by MySQL, it is deprecated now. If you want to ensure your results come back sorted, add ORDER BY. 'Future you' will thank you for it.
I am working on Educational project where i came across simple logic. I have two table month and semester_type. bellow are their schema and data;
month table
month_id month_name month_value lupdate
1 January 1
2 February 2
3 March 3
4 April 4
5 May 5
6 June 6
7 July 7
8 August 8
9 September 9
10 October 10
11 November 11
12 December 12
here is my semester_type table;
semester_type_id semester_type_name start_month end_month
1 Fall 8 12
2 Summer 1 4
and here is the output i want;
Semester Name Start Month End Month
Fall August December
Summer January April
i am confused with inner joining the month_id with start_month and end_month columns in both tables. can someone help me with codeigniter query
Join month's table twice with your semester table
select s.semester_type_name,
m.month_name start_month ,
m1.month_name end_month
from semester s
join month m on(m.month_id = s.start_month)
join month m1 on(m1.month_id = s.end_month)
Demo
Using codeigniter's active record library you can write it as
$this->db->select('s.semester_type_name,m.month_name start_month ,m1.month_name end_month')
->from('semester s')
->join('month m','m.month_id = s.start_month')
->join('month m1','m1.month_id = s.end_month')
->get()
->result();
I am trying to count the number of events in the subchannel column of my l_events table between the dates 2013-10-01 and 2014-03-31 and group by specific subchannel, year and month.
Right now my results look like:
year month subchannel count(*)
2013 10 creativemornings 1
2014 3 creativemornings 2
2013 11 founderinstitute 1
I would like my results to include rows for each specific subchannel where no events occurred occurred in that month. So something like:
year month subchannel count(*)
2013 10 creativemornings 1
2013 11 creativemornings 0
2013 12 creativemornings 0
2014 1 creativemornings 0
2014 2 creativemornings 0
2014 3 creativemornings 2
2013 10 founderinstitute 0
2013 11 founderinstitute 1
2013 12 founderinstitute 0
2014 1 founderinstitute 0
2014 2 founderinstitute 0
2014 3 founderinstitute 0
I tried to join my query to my calendar table (which includes a datetime column of all relevent dates) but it didn't work. Any thoughts?
SELECT
year(l.created) as year,
month(l.created) as month,
l.subchannel,
count(*)
FROM db.l_events l
right JOIN db.calendar c
ON (date(l.created) = c.datefield)
WHERE
l.created between '2013-10-01' and '2014-03-31'
group by
l.subchannel,
year(l.created),
month(l.created)
;
This will do it. It creates a Cartesian product of your subchannel list and your calendar table and LEFT JOINs the l_events table to that result set.
SELECT
year(c.datefield) as year,
month(c.datefield) as month,
s.subchannel,
count(l.created)
FROM db.calendar c
CROSS JOIN (select distinct subchannel from l_events) s
LEFT JOIN db.l_events l
ON (date(l.created) = c.datefield)
AND l.subchannel = s.subchannel
Where c.datefield between '2013-10-01' and '2014-03-31'
group by
s.subchannel,
year(c.created),
month(.created)
order by
s.subchannel,
year(c.created),
month(.created)
;