Stored procedure to subtract from column with same dates - mysql

I have the following columns:
2022-05-25T17:31:34+0000 92 7 1
2022-05-25T16:06:46+0000 50 5 9
2022-05-25T13:05:27+0000 91 10 106
2022-05-25T09:17:01+0000 48 4 4
2022-05-25T08:43:05+0000 60 4 2
2022-05-25T06:26:38+0000 24 3 6
2022-05-24T15:14:49+0000 55 12 6
2022-05-24T12:25:35+0000 43 8 2
2022-05-24T11:15:24+0000 66 7 2
2022-05-24T10:45:56+0000 37 15 2
2022-05-23T17:51:09+0000 59 7 1
2022-05-23T17:50:44+0000 47 6 3
2022-05-23T15:48:02+0000 126 7 13
2022-05-23T11:42:26+0000 64 9 9
2022-05-27T06:00:29+0000 3 0 1
2022-05-25T17:31:34+0000 96 7 1
2022-05-25T16:06:46+0000 55 5 9
2022-05-25T13:05:27+0000 99 11 116
2022-05-25T09:17:01+0000 52 4 15
2022-05-25T08:43:05+0000 61 4 2
2022-05-25T06:26:38+0000 26 3 6
2022-05-24T15:14:49+0000 57 13 7
2022-05-24T12:25:35+0000 43 8 2
2022-05-24T11:15:24+0000 66 7 2
2022-05-24T10:45:56+0000 38 15 2
2022-05-23T17:51:09+0000 59 7 1
2022-05-23T17:50:44+0000 47 6 3
2022-05-23T15:48:02+0000 127 7 13
If you look at the 16th row it has the same date as the first row but the number of PostLikes are different (92 and 96) PostComments and PostShares also change. I want to create a stored procedure where when I input the date it will return the difference. For example, if I select the third row with date 2022-05-25T13:05:27+0000 it should give the result:
DateT PostLikes PostComments PostShares
2022-05-25T13:05:27+0000 7 1 10
Now one method of doing this is:
select max(PostLikes) - min(PostLikes) as LikeDifference, max(PostComments) - min(PostComments) as CommentDifference, max(PostShares) - min(PostShares) as ShareDifference
from kpitb.userLikes
where DateT = "2022-05-25T17:31:34+0000";
But this method is only good if there are two values, the database is going to have several values with the same dates. (Note DateT is VARCHAR)
For e.g.
Row 1 2022-05-25T13:05:27+0000 24
Row 2 2022-05-25T13:05:27+0000 34
Row 3 2022-05-25T13:05:27+0000 67
How to find the difference.
Any help would be appreciated.

Using window functions you can find the max id and the previous values and the main query becomes trivial.
with cte as
(select t.*,
lag(postlikes) over(partition by datet order by id) prevlikes,
lag(postcomments) over(partition by datet order by id) prevcomments,
lag(postshares) over(partition by datet order by id) prevshares,
t1.maxid
from t
join (select max(id) maxid,datet from t group by datet) t1 on t1.datet = t.datet
order by datet,id
)
select datet,
case when prevlikes is null then postlikes else postlikes - prevlikes end likes,
case when prevcomments is null then postcomments else postcomments - prevcomments end comments,
case when prevshares is null then postshares else postshares - prevshares end shares
from cte
where id = maxid;
https://dev.mysql.com/doc/refman/8.0/en/window-functions.html

Related

MYSQL GROUP BY and SUM with clause

Hello there are two tables
Interval
id
is_full
1
1
2
0
3
0
entry_penalty
interval_id
entry_id
amount
2
14
55
3
14
7
3
14
1
1
15
4
1
15
8
2
15
11
So i am trying to display Sum of all entry_penalties per interval, twist is even if there is no relation between entry_penalty and interval table i should display full course interval sum per entry_id (related to is_full field).
For example total results should be in this case
interval_id
entry_id
amount
1
14
63
2
14
55
3
14
8
1
15
23
2
15
11
I have tried with sub query but it ignores to do calculation when there is no relation between entry_penalties and interval tables regarding is_full column.
My code so far.
SELECT
ep.interval_id,
IF (
i.is_full,
(
SELECT SUM(ep2.amount) * 1000 FROM entry_penalty as ep2
WHERE ep2.entry_id = ep.entry_id
),
SUM(ep.amount) * 1000
) as penalty_time,
ep.entry_id
FROM entry_penalty ep
INNER JOIN \`interval\` i ON i.id = ep.interval_id
WHERE ep.entry_id IN (:entryIds)
GROUP BY interval_id, entry_id`
I would propose to deal with the two cases (full, not full) separately, and then use union all to combine the two results:
SELECT i.id, ep.entry_id, SUM(ep.amount)
FROM `interval` i,
entry_penalty ep
WHERE i.is_full
GROUP BY i.id, ep.entry_id
UNION ALL
SELECT i.id, ep.entry_id, SUM(ep.amount)
FROM entry_penalty ep
INNER JOIN `interval` i
ON ep.interval_id = i.id
AND NOT i.is_full
GROUP BY i.id, ep.entry_id
ORDER BY 2, 1
See it run on dbfiddle.uk, where it outputs:
id
entry_id
SUM(ep.amount)
1
14
63
2
14
55
3
14
8
1
15
23
2
15
11

Mysql group by customer and get last 3 records

Sql Table
Sales Date order Id customer_id medium
07-07-2018 WP241530914666620 26 4
21-07-2018 WP241532133344497 26 4
29-07-2018 WP241532821589511 26 4
01-07-2018 1100070191 61 3
05-07-2018 1100071337 61 3
11-07-2018 1100073077 61 3
15-07-2018 1100074754 61 3
21-07-2018 1100075959 61 3
25-07-2018 1100077484 61 3
01-07-2018 100207654 64 3
07-07-2018 100210077 64 3
08-07-2018 WP241531004708220 64 4
Result:-
Sales Date order Id customer_id medium
07-07-2018 WP241530914666620 26 4
21-07-2018 WP241532133344497 26 4
29-07-2018 WP241532821589511 26 4
01-07-2018 1100070191 61 3
05-07-2018 1100071337 61 3
11-07-2018 1100073077 61 3
i need mysql query for above result .
last 3 orders for each customers in above table . i am trying some codes but unable to get results for the above
You could using correlated subqueries like:
select Sales_Date,order_Id,customer_id,medium
from
(select y1.Sales_Date,y1.order_Id,y1.customer_id,y1.medium,
(select count(*)
from 'yourtable' y2
where y2.customer_id=y1.customer_id
and (y2.Sales_Date < y1.Sales_Date or y2.Sales_Date = y1.Sales_Date)
) rn
from 'yourtable' y1
) finalresult
where rn<=3
Reference:
correlated subqueries
Example

mysql join two table rows in one table

I have two tables e_sku and e_availability, In e_sku table i have 45 rows with the default availability as 1, below is an example
id is_available name
1 1 UN001N
2 1 UN002N
3 1 UN003N
4 1 UN004N
5 1 UN005N
6 1 UN006N
7 1 UN007N
8 1 UN008N
9 1 UN009N
10 1 UN010N
11 1 UN011N
12 1 UN012N
13 1 UN013N
14 1 UN014N
15 1 UN015N
16 1 UN016N
17 1 UN017N
18 1 UN018N
19 1 UN019N
20 1 UN020N
21 1 UN021N
22 1 UN022N
23 1 UN023N
24 1 UN024N
25 1 UN025N
26 1 UN026N
27 1 UN027N
28 1 UN028N
29 1 UN029N
30 1 UN030N
31 1 UN031N
32 1 UN032N
33 1 UN033N
34 1 UN034N
35 1 UN035N
36 1 UN036N
37 1 UN037N
38 1 UN038N
39 1 UN039N
40 1 UN040N
41 1 UN041N
42 1 UN042N
43 1 UN043N
44 1 UN044N
45 1 UN045N
Second table is e_availability in this table i am only storing the unavailability with dates below is the example
id e_sku_id is_available working_date
1 5 0 10/20/2016
2 8 0 10/20/2016
3 10 0 10/20/2016
4 1 0 10/20/2016
5 15 0 10/20/2016
6 11 0 10/19/2016
7 1 0 10/19/2016
Because the data is capturing every date for unavailability so i am only gathering the unavailable product's data in e_availability table w.r.t. dates, Now i am looking to show the data for each day as complete skus in such a way that every day report will show 45 skus and for available sku it will show 1 from e_sku table's column is_available and for unavailable sku it will show the column of is_availability from e_availability table
I am using mysql database, I tried many join queries but not getting the report.
can any one guide about which join i require
I got the result by using this query
SELECT * FROM (SELECT id,NAME,1 AS is_available FROM e_sku
WHERE company_id = 2
AND id NOT IN (SELECT id FROM (SELECT e_sku.id,e_sku.name, edge_availability.is_available FROM edge_availability
JOIN edge_working ON edge_working.`id` = edge_availability.`working_id`
JOIN e_sku ON e_sku.id = edge_availability.`sku_id`
WHERE edge_working.`working_date` = '2016-10-19' AND edge_availability.`store_id` = 84) X)
UNION
SELECT e_sku.id,e_sku.name, edge_availability.is_available FROM edge_availability
JOIN edge_working ON edge_working.`id` = edge_availability.`working_id`
JOIN e_sku ON e_sku.id = edge_availability.`sku_id`
WHERE edge_working.`working_date` = '2016-10-19' AND edge_availability.`store_id` = 84) Y
ORDER BY id
You can use a LEFT JOIN to detect when a date isn't found in the e_availability table. The join will return NULL for all the columns in that table, then you can default to the value from e_sku.
SELECT d.date, s.id, IFNULL(a.is_available, s.is_available) AS is_available
FROM all_dates AS d
CROSS JOIN e_sku AS s
LEFT JOIN e_availability ON d.working_date = a.date AND s.id = a.e_sku_id
You need to create an additional table all_dates that contains all the dates that you want to report on. See What is the most straightforward way to pad empty dates in sql results (on either mysql or perl end)? for how you can create such a table dynamically.

How can I get the id, min and max in the same My SQL query?

I have 2 tables: stops and bus_route_details.
stop_id stop_name
1 ā€˜Cā€™ CROSS ROAD JUNCTION
2 10TH ROAD
3 16TH ROAD
4 4TH ROAD (GOLIBAR)
5 600TENAMENTGATE
6 A.D.MODI INSTITUTE
7 AHANSARI CHOWK
8 A.H.SCHOOL
9 A.P.M.COMPLEX
10 A.T.I.
11 AAI TULJABHAVANI CHOWK/LOKHANDWALA COMPLEX
12 AAKASH GANGA SOCIETY (DHARAVI)
The table stops simply stores the id and name of each stop. The bus_route_details table stores the bus_number, the stop_id of the stop from the stops table and the order in which the stop appears on that route. The first stop has the order 1 whereas the last stop can be a number like 44 if the route has 44 stops in total.
bus_number stop_id stop_order
8 2139 30
8 351 31
8 1791 32
8 19 33
8 2 34
8 497 35
8 2024 36
8 20 37
8 404 38
8 1787 39
8 621 40
8 1937 41
8 1941 42
7 509 1
7 788 2
7 996 3
7 1340 4
7 1161 5
7 335 6
7 2296 7
7 891 8
As per the above, I would like to get a table that shows where bus number 7 and 8 start and end.
In simple words, get the distinct list of bus numbers, find the stop which minimum stop order and maximum stop order for each bus.
7, start, end [This is how I want the bus numbers and stop names]
My current query only gives me 2 columns: either the starting or the ending stop_name. How can I retrieve all 3 columns in the same query?
SELECT bus_number, stop_name from bus_route_details, stops `WHERE(bus_number, stop_order) IN (SELECT bus_number, MAX(stop_order)`
FROM bus_route_details
GROUP BY bus_number)
AND stops.stop_id = bus_route_details.stop_id
Any suggestions? I did the UNION and got all 4 results successfully in 2 columns but I would like 3 columns for this. Thank you
One way of doing this is to find the min and max in a derived table and join the stops table and finally use conditional aggregation to flatten the result, like this:
select
b.Bus_number,
max(case when b.stop_order = x.mio then b.stop_id end) min_stop_id,
max(case when b.stop_order = x.mio then s.stop_name end) min_stop_name,
max(case when b.stop_order = x.mao then b.stop_id end) max_stop_id,
max(case when b.stop_order = x.mao then s.stop_name end) max_stop_name
from bus_route_details b
join (
select Bus_number, min(stop_order) mio, max(stop_order) mao
from bus_route_details
group by Bus_number
) x on b.Bus_number = x.Bus_number and (b.stop_order = x.mio or b.stop_order = x.mao)
join stops s on b.stop_id = s.stop_id or b.stop_id = s.stop_id
group by b.Bus_number;
This would give you a result like:
Bus_number min_stop_id min_stop_name max_stop_id max_stop_name
----------- ----------- -------------------- ----------- --------------------
7 509 stop 1 891 stop 2
8 351 stop 3 1941 stop 4
Use double inner join on stops
select b.stop_name as name_start, c.stop_name as finish_name
from
( SELECT bus_number, min(stop_order) as start_id, max(stop_order) as finish_id
from bus_route_details
group by bus_number) as t
inner join bus_route_details as b on t.start_id = b.stop_id
inner join bus_route_details as c on t.finish_id = c.stop_id

MySQL Select Last n Rows For List of ID'S

Fixture Table
uid home_uid away_uid winner date season_division_uid
1 26 6 6 2013-07-30 18
2 8 21 8 2013-06-30 18
3 6 8 8 2013-06-29 18
4 21 26 21 2013-05-20 18
5 6 26 6 2013-04-19 18
This table contains hundreds of rows.
Currently I have a query to select all the teams in a division, i.e.
SELECT team_uid
FROM Season_Division_Team
WHERE season_division_uid='18'
which lists the rows of team uid's i.e. [6,26,8,21,26].
Now for each of the unique team ids, I would like to return the last 3 winner values, ordered by the date column, that they were involved in (they could be an away_uid or home_uid).
So the returned value example would be:
team_id winner date
6 6 2013-07-30
6 8 2013-06-29
6 26 2013-04-19
26 6 2013-07-30
26 21 2013-05-20
26 6 2013-04-19
Any ideas? Thank you
Im not sure how to get it direct, a query like
select * from Season_division_Team where
`date >= (select min(`date`) from
(select `date` from season_division_team order by date desc limit 3))
and (home_uid = 6 or away_uid = 6)
Thats not going to be a good query. But only way i can think of currently
Its hard to get the 3rd largest value from SQL Example
the sub query is trying to get the date where the last win occured, and then getting all dates after that where the team played.
EDIT:
SELECT * FROM Season_Division_Team WHERE winner = 6 ORDER BY `date` DESC LIMIT 3
that sounds more like your latter comment