A have a reservation that looks something like this:
id payable time name floor
1 24 02:40:10 Benjamin 15th
2 36 02:29:10 Beverlyn 15th
3 48 02:35:16 Benjamin 15th
4 30 02:32:51 Beverlyn 15th
And an orders table where the orders details of a customer is stored.
id product
1 A
2 B
3 C
4 D
I want to return ONLY latest record from each user that is inserted. Something like this:
payable time name floor product
24 02:40:10 Benjamin 15th A
30 02:32:51 Beverlyn 15th D
attempted query:
SELECT reservation.payable, reservation.time, reservation.name, reservation.floor, orders.product
FROM orders
INNER JOIN reservation
ON orders.id = reservation.id
WHERE reservation.time =
(SELECT MAX(time)
FROM reservation)
&& reservation.floor='15th';
problem is it only returns a SINGLE record who last inputted a even names are of the users different. Which is in the case only returns this:
payable time name floor product
24 02:40:10 Benjamin 15th A
use corelated subquery
SELECT r.*,o.product
FROM reservation r
join order o ON o.id = r.id
where r.time =( select max(time) from reservation r1 where r1.name=r.name)
Using joins -
SELECT t1.payable,
t1.time,
t1.NAME,
t1.floow,
t3.product
FROM reservation t1
INNER JOIN
(
SELECT Max(time) max_time,
NAME
FROM reservation
GROUP BY NAME) t2 t1.NAME=t2.NAME
AND t1.time=t2.max_time
INNER JOIN product t3
ON (
t1.id=t3.id)
SELECT r.payable, r.time, r.name, r.floor, o.product
FROM orders as o
INNER JOIN reservation as r
ON o.id = r.id
WHERE r.time =
(SELECT MAX(time)
FROM reservation where name=r.name)
&& r.floor='15th';
You can try something like this:
/* Create tables */
CREATE TEMP TABLE orders AS
(
SELECT 1 AS id, 'A' AS product UNION
SELECT 2, 'B' UNION
SELECT 3, 'C' UNION
SELECT 4, 'D'
);
CREATE TEMP TABLE reservations AS
(
SELECT 1 AS id, 24 AS payable, '02:40:10'::TIME AS time, 'Benjamin' AS name, '15th' AS floor UNION
SELECT 2, 36 , '02:29:10 '::TIME, 'Beverlyn', '15th'UNION
SELECT 3, 48 , '02:35:16'::TIME, 'Benjamin', '15th'UNION
SELECT 4, 30 , '02:32:51 '::TIME, 'Beverlyn', '15th'
);
/* Final Selection */
SELECT a.id
, a.payable
, a.time
, a.name
, a.floor
, b.product
FROM reservations a
LEFT JOIN orders b on a.id = b.id
WHERE (name, time) IN (SELECT name, MAX(time) AS time
FROM reservations
GROUP BY 1)
ORDER BY 1;
Alternately you can also use window functions.
Related
I have patients table and appointments table. I want to query appointments from today and join patient info on the query.
This
SELECT a.PatientID, a.DoctorID, a.DT,
p.id, p.Name
FROM appointment a
JOIN Patient p
ON p.id = a.PatientID
WHERE DATE(DT) = CURDATE()
GROUP BY p.id
ORDER BY a.DT DESC
Works, but it shows the first row it finds (usually the older one) not respecting the order by (to show only the latest by patient). What am I missing here?
UPDATE:
Sorry, I should write it more properly.
Patient table:
id Name
1 Jonathan
2 Helena
Appointment table
PatientID DoctorID DT
1 1 2021-08-27 09:30
2 1 2021-08-27 10:00
1 1 2021-08-27 11:00
If I query as I have it, the return will be
1 1 2021-08-27 09:30
2 1 2021-08-27 10:00
Instead of
2 1 2021-08-27 10:00
1 1 2021-08-27 11:00
Use window function for retrieving the patient wise latest date record. Then join patient table. If all patient info is needed then use LEFT JOIN instead of INNER JOIN.
-- MySQL (v5.8)
SELECT p.id PatientID
, p.Name patient_name
, t.DoctorID
, t.DT
FROM Patient p
INNER JOIN (SELECT PatientID
, DoctorID
, DT
, ROW_NUMBER() OVER (PARTITION BY PatientID ORDER BY DT DESC) row_num
FROM Appointment) t
ON p.id = t.PatientID
AND t.row_num = 1
ORDER BY t.DT;
Please check from url https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=944f2dd72105bc9fb06b1a6b5fd837f2
For lower version where window functions are not supported.
-- MySQL(v5.6)
SELECT p.id PatientID
, p.Name patient_name
, tmp.DoctorID
, tmp.DT
FROM Patient p
INNER JOIN (SELECT #row_no := IF(#prev_val = t.PatientID, #row_no + 1, 1) AS row_number
, #prev_val := t.PatientID PatientID, t.DoctorID, t.DT
FROM Appointment t,
(SELECT #row_no := 0) x,
(SELECT #prev_val := 0) y
ORDER BY t.PatientID, t.DT DESC) tmp
ON p.id = tmp.PatientID
AND tmp.row_number = 1
ORDER BY tmp.DT;
Please check from url https://dbfiddle.uk/?rdbms=mysql_5.6&fiddle=d665ffe9f3d09df23513ad50be31b388
I want to select the rows from products table.
The products are season based.
each product row/entity contains a column named id_season
and seasons table looks like
id | season_name | active | created | modified
Season names are Year like 2016,2017,2018 ...
I want to select all the products from 2016 and 2017 which have same code
I have a simple select like
SELECT *
FROM products P
INNER JOIN seasons S ON S.id = P.id_season
WHERE S.active = 1
AND S.season_name IN ( YEAR(GETDATE()), YEAR(GETDATE()) + 1 )
but don't know how to refine it, to match the codes on products from different seasons.
Try with the below code..
;WITH cte_1
AS
(SELECT *,COUNT(p.code) OVER(partition by p.code Order by p.code) cnt
FROM products P
INNER JOIN seasons S ON S.id = P.id_season
WHERE S.active = 1
AND S.season_name IN ( YEAR(GETDATE()), YEAR(GETDATE()) + 1 )) -- or simply put IN ('2016','2017')
SELECT *
FROM cte_1
WHERE cnt>1
or you can use a subquery format as below.
SELECT *
FROM
(SELECT *,COUNT(p.code) OVER(partition by p.code Order by p.code) cnt
FROM products P
INNER JOIN seasons S ON S.id = P.id_season
WHERE S.active = 1
AND S.season_name IN ( YEAR(GETDATE()), YEAR(GETDATE()) + 1 )) t
WHERE t.nt>1
You can use inner query as follows:
SELECT * FROM products
where id_season in (Select id from seasons where
season_name IN ( YEAR(GETDATE()), YEAR(GETDATE()) + 1 ));
I have 2 tables;
banner_views (id, b_id, b_date)- this record a banner view every time it gets displayed
banners_dynamic (id, status, static_iname, static_keywords, static_url, static_alt, static_type, static_image, b_views, b_clicks) - stores the banner data
I would like to select 3 banners_dynamic results which have had the least views in the last 7 days.
I did put somethign together (see below) but I realised it was grabbing the total views for all banner rather than uniquely by id.
SELECT *,
(SELECT COUNT(*) FROM banner_views v WHERE v.b_date >= DATE(NOW()) - INTERVAL 7 DAY) as post_count
FROM banners_dynamic b
WHERE static_keywords LIKE '%test%' AND b.status='1' AND b.static_type='1'
ORDER BY post_count ASC LIMIT 3
Can anyone point me in the correct direction?
You must join both banners_dynamic table and your subquery with corresponding banner IDs:
SELECT
b.*, p.b_count
FROM
banners_dynamic b
INNER JOIN (
SELECT
b_id,
COUNT(*) AS b_count
FROM
banner_views v
WHERE
v.b_date >= DATE(NOW() - INTERVAL 7 DAY)
GROUP BY
b_id
) p on p.b_id = b.id
WHERE
b.static_keywords LIKE '%test%'
AND b.`status` = '1'
AND b.static_type = '1'
ORDER BY
p.b_count ASC
LIMIT 3
UPDATE: You can do it even without subquery:
SELECT
b.*, COUNT(v.b_id) AS b_count
FROM
banners_dynamic b
INNER JOIN banner_views v ON v.b_id = b.id
WHERE
v.b_date >= DATE_ADD(NOW(), INTERVAL - 7 DAY)
AND b.static_keywords LIKE '%test%'
AND b.`status` = '1'
AND b.static_type = '1'
GROUP BY
v.b_id
ORDER BY
b_count ASC
LIMIT 3;
If you want to include banners without any views (count=0) then you must do a LEFT JOIN:
SELECT
b.*, COUNT(v.b_id) AS b_count
FROM
banners_dynamic b
LEFT JOIN banner_views v ON v.b_id = b.id
AND v.b_date >= DATE_ADD(NOW(), INTERVAL - 7 DAY)
WHERE
b.static_keywords LIKE '%test%'
AND b.`status` = '1'
AND b.static_type = '1'
GROUP BY
v.b_id
ORDER BY
b_count ASC
LIMIT 3;
these is my DB table data,{ i have maintained only one Table}
I need to fetch max 3 data from each start_date,
give me any idea to develop query,,
SELECT a.*
FROM Table1 a
INNER JOIN Table1 b ON a.start_date = b.start_date AND a.event_id <= b.event_id
GROUP BY a.event_id,a.start_date
HAVING COUNT(*) <= 3
ORDER BY a.start_date
I may suggest you this query -
SELECT * FROM (
SELECT t1.*, COUNT(*) pos FROM table t1
LEFT JOIN table t2
ON t2.start_date = t1.start_date AND t2.event_id <= t1.event_id
GROUP BY
t1.start_date AND t1.event_id
) t
WHERE
pos <= 3;
It selects 3 rows with min event_id in a start_date group.
I'm trying to take data from three different tables and output it using as few queries and as little PHP code as possible.
Listed below are the tables I have and the columns in each (only listing relevant columns).
exp_members (A)
columns: member_id, group_id
exp_brandrelations (B)
columns: member_id, brand_id
exp_du_mktgmats (C)
columns: du_id, brand_id, date
I want to loop through the members who belong to group_id='5' (from A), determine which brands are assigned to each member (from B), and get a list of du_ids (from C) that correspond to each member, that have been INSERTed in the last 24 hours.
So far, I can get a list of members in group 5:
SELECT member_id, brand_id FROM exp_brandrelations
WHERE member_id IN (SELECT member_id FROM exp_members where group_id = 5)
And I can get a list of du_ids from the last 24 hours:
SELECT du_id FROM exp_du_mktgmats
WHERE date >= DATE_SUB(NOW(), INTERVAL 1 DAY)
But I'm not sure how best to tie it all together.
This should do it!
SELECT m.member_id, b.brand_id, d.du_id FROM exp_members m, exp_brandrelations b, exp_du_mktgmats d WHERE m.group_id = '5' AND m.member_id = b.member_id AND b.brand_id = d.brand_id AND d.date >= DATE_SUB(NOW(), INTERVAL 1 DAY)
SELECT du_id FROM exp_members m, exp_brandrelations r, exp_du_mktgmats a
WHERE a.brand_id=r.brand_id AND r.member_id=m.member_id
AND date >= DATE_SUB(NOW(), INTERVAL 1 DAY)
AND m.group_id='5'
SELECT
c.du_id
FROM
exp_du_mktgmats c
LEFT JOIN
exp_brandrelations b
ON
c.brand_id = b.brand_id
LEFT JOIN
exp_members a
ON
b.member_id = a.member_id
WHERE
a.group_id = 5
AND
c.date >= DATE_SUB(NOW(), INTERVAL 1 DAY);