Mysql group by customer and get last 3 records - mysql

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

Related

Stored procedure to subtract from column with same dates

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

Is there a way to have a conditional statement for comparing of tables using MySQL only?

I am having a dilemma from comparing my tables.
My problem is, I want to get each sum, which depends on the pricing. Here is the table.
Main table
main_id main_price main_date_created
25 8.5 2019-08-16
26 11.5 2019-08-01
Total table
id main_id total_price date_generated
1 25 10 2019-08-16
2 25 10 2019-08-17
3 25 10 2019-08-18
4 25 10 2019-08-19
5 25 10 2019-08-20
6 25 10 2019-08-21
7 26 20 2019-08-01
8 26 5 2019-08-02
9 26 5 2019-08-03
10 26 10 2019-08-04
Price History table
id main_id changed_main_price price_date_changed
1 25 15 2019-08-18
2 26 20 2019-08-03
I don't know if there is a way to do this just by using MySQL, what I am trying to achieve is, the Total table will be sum by MONTH and YEAR and will be multiplied by their designated price that depends on the date whether if the price has changed or not . the SUM will from each month will be generated by multiplying with the main price in the Main table but if the price had changed from its original price which it is on the Price history table
The output should be like this if the conditional is possible:
id main_id total_price price_generated (which is the prices) date
1 25 170 (10+10*8.5) 8.5
2 25 610 (10+10+10+10*15) 15
3 26 287.5 (20+5*11.5) 11.5
4 26 300 (5+10*20) 20
Here is my existing query,
SELECT m.main_id
, m.main_price
, SUM(t.total_price) total_generated
, t.date_generated
FROM main m
INNER JOIN total t
ON m.main_id = t.main_id
GROUP
BY MONTH(t.date_generated);
I know that my query is not enough, and I still don't know if my idea is really possible :(.
I racked my brain. hahaha Is this you're after?
SELECT pricelist.id, pricelist.price, SUM(t.total_price), SUM(t.total_price) * pricelist.price,
year( pricelist.latestdate), month(pricelist.latestdate),
year( t.total_date_generated), month(t.total_date_generated)
from totaltable as t
LEFT JOIN (
(
select main_id as id, main_price as price, main_date_created as latestdate
from maintable
)
UNION ALL
(
select total_main_id, changed_main_price , price_date_changed
from pricehistorytable
)
) as pricelist on pricelist.id = t.total_main_id
GROUP BY pricelist.id , t.total_price, pricelist.price,
year( pricelist.latestdate), month(pricelist.latestdate),
year( t.total_date_generated), month(t.total_date_generated) ;

Find repeated battles

I have one table with the following fields:
battle_id, winner, looser
1 200 44
2 55 366
3 44 200
4 123 200
5 200 44
6 55 366
7 177 205
8 188 211
9 366 55
10 55 366
right now it has about 1300 records (its small), and there are about 400 players, in each battle there can only be a winner and a looser (there are no draws)
how can i find all the repeated battles? i do not want to find all the repeated battles of one player, i do want to know all the repeated battles of all the players...i know that i cam make a recursive function in php that iterates over all the battles and assign them to a matrix, but just for fun...is there a way to do it only on mysql?
And how can i optimize the table to find the repeated battles more quickly?
regards
EDIT:
For example i want the query to show:
battle_id, winner, looser
1 200 44
2 55 366
3 44 200
5 200 44
6 55 366
9 366 55
10 55 366
This should work, using a self-join could result in many duplicated entries
SQLFIDDLE
SELECT
t1.battle_id,
t1.winner,
t1.loser
FROM
your_table t1
WHERE
EXISTS (
SELECT
1
FROM
your_table t2
WHERE
( ( t1.winner = t2.winner
AND t1.loser = t2.loser )
OR ( t1.loser = t2.winner
AND t1.winner = t2.loser ) )
AND t1.battle_id <> t2.battle_id
)
try this:
SELECT b1.battle_id,
b1.winner,
b1.looser
FROM battles as b1
group by b1.battle_id, b1.winner, b1.looser
having count(*)>=2

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

simple sql select over 3 tables

I'm stuck with Mysql... I'm sure this question have been asked hundreds of times but without any keyword. I've 2 tables and a view:
tbl_user_measure
measure_cat userid amount
------------------------------
7 1 78
5 1 96
4 1 78
tbl_itemcat_measure
measure_cat item_cat
----------------------
7 1
5 1
4 1
vw_allitems
measure_cat min max item_cat itemid
---------------------------------------------------
7 76 81 1 1
5 97 100 1 1
4 79 81 1 1
7 76 81 1 11
5 95 97.5 1 11
4 76 79 1 11
4 33 12 2 5
What I'm looking for is the item(s) whose min and max values match in all measure_cat's of the specific item_cat the users values (max > tbl_user_measure.amount > min).
My approach was
SELECT distinct
v.itemid,
v.measure_cat_id,
v.min,
v.max
FROM
vw_allitems v, tbl_user_measure um, tbl_user u
where
um.tbl_measure_category_id = v.measure_cat_id and
(um.amount >= v.min and um.amount <= v.max) and
v.productid = 1
This resultes in:
itemid measure_cat_id min max
---------------------------------------------------
1 7 76 81
7 7 76 81
10 7 76 81
11 7 76 81
11 4 76 79
11 5 95 9
What I need is just the itemid '11' because its values fit in all categories.
Looks like you're almost there. Your query returns all matching rows; change it so that it returns the itemid and the count, grouped by itemid. All that's left is just to return those items where the count is equal to the number of rows that user has in the first table.
UPDATE: This should do what you need:
SELECT x.itemid, x.measure_cat, x.min, x.max
FROM
(SELECT vw.itemid i, u.userid u, count(*) mc
FROM vw_allitems vw
JOIN tbl_user_measure u ON vw.measure_cat=u.measure_cat
WHERE u.amount>=vw.min and u.amount<=vw.max
GROUP BY vw.itemid, u.userid) match_counts
JOIN
(SELECT userid u, count(*) uc
FROM tbl_user_measure
GROUP BY userid) user_counts
ON match_counts.u = user_counts.u
AND match_counts.mc=user_counts.uc
JOIN
vw_allitems x
ON match_counts.i = x.itemid
WHERE match_counts.u=1
Quick walkthrough. The first subquery takes every combination of user and item, and counts the number of matches. The second subquery counts how many entries that user has in tbl_user_measure. The join selects just those users and items where the match count equals the total count for that user (i.e. all the user's entries match), then finally we join it to the original data to return the original rows from vw_allitems and select just the user we are interested in.
Try this query:
SELECT v.itemid,
v.measure_cat_id,
v.min,
v.max
FROM vw_allitems as v,
INNER JOIN tbl_user_measure as um
ON um.measure_cat = v.measure_cat and um.amount >= v.min and um.amount <= v.max
INNER JOIN tbl_itemcat_measure as im
ON im.item_cat=um.item_cat