SQL DATA BASE QUERY - mysql

City
Id Name
1 Delhi
2 Noida
3 Gurugram
Parameter
Id Name
1 Health
2 Education
3 Employment
Rating
Id Rating City_Id Param_Id Quarter Year Value_Date
1 7.5 1 1 Q1 2017 2017-02-15
2 6.3 1 1 Q1 2017 2017-02-13
3 6.9 1 1 Q1 2017 2017-02-20
4 8.2 1 1 Q2 2017 2017-04-05
5 5.5 1 1 Q2 2018 2017-12-13
6 7.6 1 1 Q3 2017 2017-08-20
7 4.5 2 1 Q1 2017 2017-02-17
8 5.3 2 1 Q1 2017 2017-02-14
9 6.9 2 1 Q1 2017 2017-02-25
10 7.2 2 1 Q2 2017 2017-08-05
11 8.5 2 1 Q2 2018 2017-12-13
12 9.6 2 1 Q3 2017 2017-08-20
13 3.5 3 1 Q2 2018 2017-12-14
14 4.6 3 1 Q4 2017 2017-08-17
15 5.5 3 1 Q2 2018 2017-12-20
16 7.6 3 1 Q3 2017 2017-08-15
17 7.5 3 1 Q2 2018 2017-12-18
18 8.6 3 1 Q3 2017 2017-08-24
19 7.5 1 2 Q1 2020 2018-05-25
20 6.3 2 2 Q3 2018 2018-17-13
21 6.9 3 3 Q2 2019 2019-06-20
I want to fetch the data from the Rating Table. I have a list of city ids, parameter ids, Quarter and Year. For Example city_id = [1,2,3], paramter_id = [1], quarter = Q3 and Year= 2017 then the output id from Rating tables should be 6, 12 and 18. 6 and 12 are fine but 18 is selected because if same quarter and year is present then we fetch the data using latest value_date.
Another case city_id = [1,2,3], paramter_id = [1], quarter = Q4 and Year= 2017 then the output id from Rating tables should be 5,11,14. 14 is fine but 5 and 11 is selected because if Quarter and year together are not present then we calculate the max date of queries period that shoub be 2017-12-31 (Q4 -2017) and apply less than equal to value_date (must be earliest)

Hmmm . . . I am thinking window functions. So filter for all rows whose year/quarter is less than or equal to the quarter you want. Then enumerate the rows backwards:
select r.*
from (select r.*,
row_number() over (partition by city_id, parameter_id order by year desc, quarter desc) as seqnum
from rating r
where city_id in (1, 2, 3) and parameter_id = 1 and
year <= 2017 and
(year < 2017 or quarter <= 'Q4')
) r
where (year = 2017 and quarter = 'Q4') or
seqnum = 1;
The filter chooses either the correct quarter or the first row.

Related

GROUP BY with MAX(date), but the date is in two separate columns

I'm trying to get the list of IDs of all the rows with latest posting date for each author in a table, for example:
id author_id date
1 12 2020-12-23
2 12 2021-01-06
3 12 2021-04-12
4 12 2021-02-10
5 17 2021-09-16
6 17 2021-05-20
7 17 2021-02-23
8 17 2021-07-02
9 24 2021-03-24
10 24 2021-02-10
11 24 2020-08-18
12 24 2020-12-14
The desired result should be:
id
3
5
9
I used this query and it works perfect:
SELECT a.id
FROM (
SELECT author_id, MAX(`date`) as MaxDate
FROM `posts_log`
GROUP BY author_id
) b
INNER JOIN `posts_log` a
ON a.author_id = b.author_id AND a.date = b.MaxDate
But let's imagine that situation changed. Now author is allowed to post only once per month. So the table changed too and 'date' column became separated:
id author_id month year
1 12 12 2020
2 12 1 2021
3 12 4 2021
4 12 2 2021
5 17 9 2021
6 17 5 2021
7 17 2 2021
8 17 7 2021
9 24 3 2021
10 24 2 2021
11 24 8 2020
12 24 12 2020
Yeah, I know, looks a little bit stupid, but this wasn't my decision. Now I have such table and I'm not allowed to change the structure.
The question is: How to get the same result with this new table. Is it possible in MySQL?
You can use similar logic. Just instead of the date, use a calculated value from year and month:
SELECT a.id
FROM (
SELECT p.author_id, MAX(p.year*100+p.month) as MaxMonth
FROM posts_log p
GROUP BY p.author_id
) b
INNER JOIN posts_log a
ON a.author_id = b.author_id AND a.year*100+a.month = b.MaxMonth;

Getting the list of all months and the number of products ordered for the month, and should have '0'for the month with no orders - mysql

I have a set of data that looks like this
Cust Id order date Ordered Product
1 Jan 2 1
1 Jan 5 2
1 March 14 1
1 September 9 1
1 December 12 2
2 Jan 5 1
2 Feb 13 2
3 March 12 2
3 April 5 3
3 June 10 2
and my output should look like this
Cust Id order Date Order product
1 Jan 31 3
1 feb 29 0
1 Mar31 1
1 Apr 30 0
1 May 31 0
1 June 30 0
1 July 31 0
1 Aug 31 0
1 Sept 30 1
1 oct 31 0
1 Nov 30 0
1 Dec 31 2
and I have got this far
1 January 31 3
1 March 31 1
1 September 30 1
1 December 31 2
and my code is
select customer_id,
date_format(last_day(order_date), '%M %d') as new_months,
sum(products_ordered) as total
from amazon_test
where customer_id =1
group by new_months, customer_id;
I currently stuck at the part where I need to have all the months and '0' as the output since no orders were made.
If you are running MySQL 8.0, one option is to use a recursive query to generate the months, and then bring the table with a left join:
with recursive months as (
select customer_id, date_format(min(order_date), '%Y-%m-01') order_date, max(order_date) max_order_date
from amazon_test
group by customer_id
union all
select customer_id, order_date + interval 1 month, max_order_date
from months
where order_date + interval 1 month < max_order_date
)
select
m.customer_id,
date_format(last_day(m.order_date), '%M %d') new_months,
coalesce(sum(t.products_ordered), 0) ordered_products
from months m
left join amazon_test t
on t.customer_id = m.customer_id
and t.order_date >= m.order_date
and t.order_date < m.order_date + interval 1 month
where m.customer_id = 1
group by m.customer_id, m.order_date
order by m.customer_id, m.order_date
I phrased the query so it actually operates on all customer_ids - if you remove the where clause in the outer query, you do get the results for all customers. If you really want the results for only one customer, you can optimize the query by pushing the where filter to the anchor of the recusive query.
Demo on DB Fiddle:
customer_id | new_months | ordered_products
----------: | :----------- | ---------------:
1 | January 31 | 3
1 | February 29 | 0
1 | March 31 | 1
1 | April 30 | 0
1 | May 31 | 0
1 | June 30 | 0
1 | July 31 | 0
1 | August 31 | 0
1 | September 30 | 1
1 | October 31 | 0
1 | November 30 | 0
1 | December 31 | 2

MySQL query to get data dynamically based on financial year

I want to select fields dynamically based on financial year (i.e., for the year of Apr'18 to Mar'19).
I have data in a table exact as given below :
ROWNO YEAR MONTH
1 2016 1
2 2016 2
3 2016 6
4 2017 7
5 2017 5
6 2018 4
7 2018 5
8 2018 6
9 2018 7
10 2018 8
11 2018 9
12 2018 10
13 2018 11
14 2018 12
15 2019 1
16 2019 2
17 2019 3
18 2019 3
19 2017 4
20 2017 1
21 2017 2
22 2018 3
I want to get the result as shown below for the financial year 2018-19 are
ROWNO YEAR MONTH
6 2018 4
7 2018 5
8 2018 6
9 2018 7
10 2018 8
11 2018 9
12 2018 10
13 2018 11
14 2018 12
15 2019 1
16 2019 2
17 2019 3
I used Query
SELECT * FROM rup_calendar WHERE YEAR BETWEEN YEAR(CURDATE()) AND YEAR(CURDATE())+1;
but not able to get exact result.
Please give me the query to get the result as given above.
Given the data you have your approach is not far away
select rowno,year,month
from t
where year * 100 + month between
case when month(now()) < 4 then (year(now()) - 1) * 100 + 3
else year(now()) * 100 + 4
end
and
case when month(now()) < 4 then (year(now())) * 100 + 3
else (year(now()) + 1) * 100 + 4
end
Notice I have calulated a yearmonth field to ease comparison. Note I haven't fully tested this and you should do so by substituting an # variable for now() to test.

laravel sum and crosstab

hi i am trying to solve this problem from 2 days please help. I have a table like below. i am trying to get crosstab display
expenditures
id name
1 exp1
2 exp2
3 exp3
4 exp4
5 exp5
stations
id name
1 station1
2 station2
3 station3
4 station4
expenses
expenditure_id station_id year month expense
1 1 2015 1 10
1 2 2015 1 20
1 3 2015 1 15
1 4 2015 1 10
1 1 2015 2 20
1 1 2015 3 30
1 1 2015 4 40
2 1 2015 1 20
2 1 2015 2 10
2 1 2015 3 20
I am trying get result like this
for year 2015
expenditure station1 station2 station3 station4
exp1 100 20 15 0
exp2 50 0 0 0
where value of station1 station2 will be the sum of month expense
This is the mysql query as your requirement, use Laravel query builder to run this query as raw query, if you donot know how to run raw query in laravel let me know, in the mean while run the query in phpmyadmin/mysql client and see whether its give you the desired output .
SELECT y.expenditure,
MAX(CASE y.station WHEN 'station1' THEN y.totalexpense END) 'station1',
MAX(CASE y.station WHEN 'station2' THEN y.totalexpense END) 'station2',
MAX(CASE y.station WHEN 'station3' THEN y.totalexpense END) 'station3',
MAX(CASE y.station WHEN 'station4' THEN y.totalexpense END) 'station4'
FROM (
SELECT exp.name AS expenditure,st.name AS station,x.totalexpense
FROM expenditures AS exp
LEFT JOIN
(SELECT expenditure_id,station_id,SUM(expense) as totalexpense
FROM expenses
WHERE year = '2015'
GROUP by expenditure_id,station_id
)
AS x ON exp.id = x.expenditure_id
LEFT JOIN stations AS st ON x.station_id = st.id
) AS y
GROUP BY y.expenditure
I assume you have only 4 stations, if stations are unknown numbers then you can use a prepared statement and create this dynamically:

How to do this query in MYSQL

Hi I have problem for create SQL. I have table and the data like this :
id month year id_type qty
1 10 2012 1 5
2 10 2012 2 4
3 10 2012 3 3
4 10 2012 4 5
5 11 2012 1 1
6 11 2012 2 2
7 12 2012 1 3
8 12 2012 2 2
I want create SQL for generating the data like this
id_type month year qty month_b4 year_b4 qty_b4
1 10 2012 5 9 2012 0
2 10 2012 4 9 2012 0
3 10 2012 3 9 2012 0
4 10 2012 5 9 2012 0
1 11 2012 1 10 2012 5
2 11 2012 2 10 2012 4
1 12 2012 1 11 2012 1
2 12 2012 2 11 2012 2
This query will do it:
select
sales.id_type as id_type,
sales.month as month,
sales.year as year,
sales.qty as qty,
prev.month as month_b4,
prev.year as year_b4,
prev.qty as qty_b4
from
sales,
sales as prev
where
sales.id_type = prev.id_type and
((sales.month=1 and prev.month=12 and prev.year=sales.year-1) or
prev.month = sales.month - 1);
I also have it on a fiddle where you can experiment with it:
http://sqlfiddle.com/#!2/ed3af/14