select data based on multiple criteria (cloest value) - mysql

I am using MySQL. I'm trying to build something and just can't find a solution to a problem.
I am selecting a value from the lookup table based on my table as shown in the below example.
Select Criteria:
my.id<>l.id AND my.route1=l.route1 AND my.route2=l.route2 AND my.utc=l.utc
where my.stime is closest or same as l.stime
ex) my.id=2's col should get the l.id=1, l.etime=7777 since my.id<>l.id and the rest are the same.
ex) my,id=5's col has options l.id=3, l.etime=9999 and l.id=4, l.etime=7979 since my.id<>l.id, my.route=l.route, my.utc=l.utc. Yet, since my.stime=2220 is closer to l.stime=2222 than l.stime=3333 , l.id=3, l.etime=9999 will be chosen.
ex) my,id=6's col example is to select either value if "closest" is the same.
ex) my,id=7's col example is to return NULL when the criteria is not met.
Table: lookup (l.)
id route1 route2 utc stime etime
---|--------|--------|-----|-------|------
1 11 22 111 1111 7777
2 11 22 111 1111 8888
3 22 33 222 2222 9999
4 22 33 222 3333 7979
5 22 33 222 3335 8989
Table: my (my.) | result
id route1 route2 utc stime | l.id l.etime
---|--------|--------|-----|------- |-------|----------|
2 11 22 111 1111 | 1 7777
5 22 33 222 2220 | 3 9999
6 22 33 222 3334 | 4or5 7979or8989
7 22 33 999 9999 | null null
A new table should be created where the result is appended to the last col of my.
Any help is appreciated. Thanks in advance.

This solution is a bit convoluted, but it's a starting point.
First, let's create an auxiliary table:
CREATE TEMP TABLE temp AS
SELECT m.id mid, l.id lid, ABS(l.stime-m.stime) timediff
FROM my m JOIN lookup l
WHERE m.route1 = l.route1 AND m.route2 = l.route2 AND
m.utc = l.utc AND m.id <> l.id;
From this table we can get the minimum timediff for each my.id:
SELECT mid, min(timediff) mtimediff FROM temp GROUP BY mid
Result:
mid mtimediff
---------- ----------
2 0
5 2
6 1
Now we can find which rows in lookup have this stime difference, and choose the smallest id:
SELECT t.mid mid, min(lid) lid
FROM temp t JOIN (
SELECT mid, min(timediff) mtimediff FROM temp GROUP BY mid
) mt ON t.mid = mt.mid AND t.timediff = mt.mtimediff
GROUP BY t.mid
This is the result:
mid lid
---------- ----------
2 1
5 3
6 4
And finally we use those ids to extract the data from the tables:
SELECT m.id, m.route1, m.route2, m.utc, m.stime, l.id, l.etime
FROM my m JOIN lookup l JOIN (
SELECT t.mid mid, min(lid) lid
FROM temp t JOIN (
SELECT mid, min(timediff) mtimediff FROM temp GROUP BY mid
) mt ON t.mid = mt.mid AND t.timediff = mt.mtimediff
GROUP BY t.mid
) ON m.id = mid AND l.id = lid;
Giving:
id route1 route2 utc stime id etime
---------- ---------- ---------- ---------- ---------- ---------- ----------
2 11 22 111 1111 1 7777
5 22 33 222 2220 3 9999
6 22 33 222 3334 4 7979

Related

How to count max value in one month from 2 table

I have 2 table on my transaction
Table One
id | date | cust_id | driver_number
1 2019-01-02 1 F 3350 NN
2 2019-04-02 2 AX 111 Z
3 2019-05-02 3 S 787 X
4 2019-05-02 4 T 9090 M
5 2019-06-02 3 P 8989 L
Table Two
driver_number | price
F 3350 NN 350000
AX 111 Z 400000
S 787 X 375000
T 9090 M 900000
P 8989 L 500000
How do I count total transaction from two tables above in one month as per requested .
In example, request for total transaction in May so the result is like below
period | total
May 1275000
Thank you
Using MONTH(T1.date) = 5 and SUM(price) the expected result is achievable
SELECT MONTH(T1.date) AS Period, SUM(price) AS `Total`
FROM TableOne T1
JOIN TableTwo T2 ON T2.driver_number = T1.driver_number
WHERE MONTH(T1.date) = 5
GROUP BY MONTH(T1.date)

How to join to single row in one to many relationship in SQL?

I want to join one to many table with single row on many table by limit 1 and order by create date
tbl_cart :
id fullname
1 myname1
2 myname2
3 myname3
tbl_cart_status:
id cart_id status created_at
1 1 33 2018-09-20
2 1 34 2018-09-23
3 2 34 2018-09-21
4 1 100 2018-09-25
5 2 35 2018-09-29
How can i get output with sql like this:
I want to get lastest status of my cart by ordered with created_at column
myname cart_id status created_at
myname1 1 100 2018-09-25
myname2 2 35 2018-09-29
Think filtering for this type of query:
select c.name, cs.*
from tbl_cart c join
tbl_cart_status cs
on c.id = cs.cart_id
where cs.created_at = (select max(cs2.created_at)
from tbl_cart_status cs2
where cs2.cart_id = cs.cart_id
);

Select one row where alert type and item id are the same and also how many similar rows

I am trying to make the notification system for my project as simple as possible on the user's side.
"john brown and 4 others liked your photo"
I tried:
Select a.id, a.item_id, a.type u.f_name, u.l_name, count(a)
From alerts
Join users on a.user_id = u.u_id
Where owner_id = {THE_USER_ID}
but it doesnt "work"
The users table
u_id | f_name | l_name
==========================
234 roy wright
654 pam brown
564 kim harris
334 tory plummer
876 rick forbes
123 paul nichol
980 mario chang
454 todd thompson
886 sam richards
215 tash gates
... ..... ........
The alerts table
id | item_id | type | user_id | owner_id
===================================================
1 21 like 234
2 21 comment 654
3 32 share 876
4 21 like 778
5 21 like 890
6 21 share 123
7 54 share 454
8 32 comment 655
9 60 comment 886
10 32 like 215
.. .. ...... ...
The results I want
id | item_id | type | u_id | f_name | l_name | amount_more
============================================================
1 21 like 234 roy wright 2
2 21 comment 654 pam brown
3 32 comment 876 rick forbes
6 21 share 123 paul nichol
7 54 share 454 todd thompson
9 60 comment 886 sam richards
10 32 like 215 tash gates
.. .. .... ... ..... ........
SELECT
MIN(CASE WHEN RowNumber = 1 THEN id END) as Id
,item_id
,type
,MIN(CASE WHEN RowNumber = 1 THEN u_id END) as u_id
,MIN(CASE WHEN RowNumber = 1 THEN f_name END) as f_name
,MIN(CASE WHEN RowNumber = 1 THEN l_name END) as l_name
,COUNT(*) - 1 as amount_more
FROM
(
SELECT
t.*
,(#rn:= if((#item = t.item_id) AND (#type = t.type),#rn + 1,
if((#item:=t.item_id) AND (#type:=t.type),1,1)
)
) as RowNumber
FROM
(SELECT *
FROM
alerts a
LEFT JOIN usersTbl u
ON a.user_id = u.u_id
WHERE
a.owner_id = 201
ORDER BY
a.item_id
,a.type
,a.id) t
CROSS JOIN (SELECT #rn:=0,#item:=0,#type:='') var
ORDER BY
item_id
,type
,id
) t2
GROUP BY
item_id
,type
ORDER BY
id
;
So you need to create a partitioned row number to identify which record you want to be considered first. Then using conditional aggregation you can choose that as your User. this works check it out here: http://rextester.com/VXZONO82847
In the Query you are not using aliases a and u properly, Use this:
Select
a.id,
a.item_id,
a.type,
u.f_name,
u.l_name,
count(a.*)
From alerts a Join users u
on(a.user_id = u.u_id)
Where owner_id = {THE_USER_ID}
group by 1,2,3,4,5;

How to count numbers for every status from history table see output

lead table
lead_id | name | mobile
3710 aaa 888888
3713 bbb 777777
3714 ccc 666666
user table
user_id | email | pass | lead_id
38 ppp ***** 3710
39 qqq ***** 3713
40 rrr ***** 3710
History table
h_id | lead_id | status | user_id
49 3710 not dobale 38
108 3713 doable 38
109 3714 pipeline 38
110 3710 converted 38
111 3715 Login 38
112 3713 converted 38
I want to count no of indivisual status for perticuler lead_id.
How to do that ?
But for lead_id 3710 that must be consider h_id 110 not 49 means greater h_id same in case of lead_id 3713
output should be like this:
ouput (for user_id 38)
status No
converted - 2 (lead_id is different)
pipeline - 1
login - 1
Try this:
SELECT h.status, COUNT(DISTINCT lead_id)
FROM History h
INNER JOIN (SELECT user_id, lead_id, MAX(h_id) h_id
FROM History
GROUP BY user_id, lead_id
) AS a ON h.user_id = a.user_id AND h.lead_id = a.lead_id AND h.h_id = a.h_id
WHERE h.user_id = 38
GROUP BY h.status
So you need to count the most recent status from the history table. You can get this with a join to an aggregation and then aggregate again. Or you can use the substring_index()/group_concat() trick:
select last_status, count(*)
from (select h.lead_id, substring_index(group_concat(status order by h_id desc), ',', 1) as last_status
from history
group by h.lead_id
) h
group by last_status;

Getting Max date from multiple table after INNER JOIN

I have two following tables
table 1)
ID | HOTEL ID | NAME
1 100 xyz
2 101 pqr
3 102 abc
table 2)
ID | BOOKING ID | DEPARTURE DATE | AMOUNT
1 1 2013-04-12 100
2 1 2013-04-14 120
3 1 2013-04-9 90
4 2 2013-04-14 100
5 2 2013-04-18 150
6 3 2013-04-12 100
I want to get reault in mysql such that it take the row from table two with MAX DEPARTURE DATE.
ID | BOOKING ID | DEPARTURE DATE | AMOUNT
2 1 2013-04-14 120
5 2 2013-04-18 150
6 3 2013-04-12 100
SELECT b.ID,
b.BookingID,
a.Name,
b.departureDate,
b.Amount
FROM Table1 a
INNER JOIN Table2 b
ON a.ID = b.BookingID
INNER JOIN
(
SELECT BookingID, MAX(DepartureDate) Max_Date
FROM Table2
GROUP BY BookingID
) c ON b.BookingID = c.BookingID AND
b.DepartureDate = c.Max_date
SQLFiddle Demo
Well,
SELECT * FROM `table2` ORDER BY `DEPARTURE_DATE` DESC LIMIT 0,1
should help