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);
Related
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.
I am having a trouble with a query.
I need to collect 2 companies from trade_directory where they have status 1 and match 3 categories.
I want to select the 2 companies on the least view first basis counted from company_views within the last 30 days.
SELECT
b.id, b.v_date, b.c_id COUNT(b.c_id) AS v_count
AND b.v_date >= DATE_ADD(NOW(), INTERVAL - 30 DAY)
FROM
company_views b
LEFT JOIN trade_directory v ON v.id = b.c_id
WHERE
v.cat1 = 'cat'
AND v.cat2 = 'rat'
AND v.cat3 = 'hat'
AND v.status = '1'
GROUP BY
b.c_id
ORDER BY
v_count ASC
LIMIT 2
Thanks
Chris
You're using AND operator in SELECT instead of WHERE
AND b.v_date >= DATE_ADD(NOW(), INTERVAL - 30 DAY)
can your try this code
SELECT
b.id, b.v_date, b.c_id COUNT(b.c_id) AS v_count
FROM
company_views b
LEFT JOIN trade_directory v ON v.id = b.c_id
WHERE
v.cat1 = 'cat'
AND v.cat2 = 'rat'
AND v.cat3 = 'hat'
AND v.status = '1'
AND b.v_date >= DATE_ADD(NOW(), INTERVAL - 30 DAY)
GROUP BY
b.c_id
ORDER BY
v_count ASC
LIMIT 2
I changed my approach (using different tables but here it what is working but it is really really slow)
SELECT o.*, COUNT(e.c_id) AS b_count
FROM cat3_entries o
LEFT JOIN company_views e ON e.c_id = o.c_id
AND e.v_date >= DATE_ADD(NOW(), INTERVAL - 30 DAY)
WHERE
o.c3_id = '81'
GROUP BY
o.c_id
ORDER BY
b_count ASC
LIMIT
3;
If I could resolve the speed issue this one would be great.
I have this query:
$sql = "SELECT m.id FROM members m
LEFT JOIN orders o ON o.user_id = m.id AND
YEAR(date) = YEAR(CURRENT_DATE - INTERVAL 1 MONTH) AND
MONTH(date) = MONTH(CURRENT_DATE - INTERVAL 1 MONTH)
LEFT JOIN transactions t ON t.user_id = o.user_id";
I need to get sum of transactions.points, so I do this:
$sql = "SELECT m.id, COALESCE(SUM(t.points), 0) AS total_points FROM members m
LEFT JOIN orders o ON o.user_id = m.id AND
YEAR(date) = YEAR(CURRENT_DATE - INTERVAL 1 MONTH) AND
MONTH(date) = MONTH(CURRENT_DATE - INTERVAL 1 MONTH)
LEFT JOIN transactions t ON t.user_id = o.user_id";
But when i execute this, I will get only rows with some transactions (and orders). What I must to do for getting 0 as total_points when no transactions found?
Text description: I want to get sum of points reward (from transactions table) of orders (orders table), where order was created in last month.
Thanks!
Get the sum of points per user and use it in the left join to get 0 when the user has no transactions.
SELECT m.id, COALESCE(t.total_points, 0) AS total_points
FROM members m
LEFT JOIN orders o ON o.user_id = m.id AND
/* use this instead of functions which prevent indexes on the date column from being used */
o.date >= date '2016-11-01' AND o.date <= date '2016-11-30'
LEFT JOIN (select user_id, SUM(points) total_points
from transactions group by user_id) t ON t.user_id = o.user_id
You need to add a GROUP BY clause to your query without which you are actually performing SUM() on the entire resultset. Not sure on which column but say on m.id
$sql = "SELECT m.id, COALESCE(SUM(t.points), 0) AS total_points FROM members m
LEFT JOIN orders o ON o.user_id = m.id AND
YEAR(date) = YEAR(CURRENT_DATE - INTERVAL 1 MONTH) AND
MONTH(date) = MONTH(CURRENT_DATE - INTERVAL 1 MONTH)
LEFT JOIN transactions t ON t.user_id = o.user_id
GROUP BY m.id";
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;
I have a table full of entries with DATETIME time stamps, and an ID field. I want to make a MySQL query (in my PHP script) that selects from another table with the matching ID. I want to make some kind of join that will sort by the number of entries in the first table with a timestamp more recent than 24 hours. So basically, if there are 30 entries in the first table with a timestamp of less than 24 hours with the ID "334" then I want to select the row from the second table with the ID of 334. And that should come before an entry with the ID "234" that only has 20 entries within the last 24 hours.
I hope this is clear... I'm really stumped on how to do this, so thanks for any help. :D
Use:
SELECT a.*,
x.num
FROM TABLE_A a
JOIN (SELECT t.id,
COUNT(*) AS num
FROM TABLE_B t
WHERE t.timestamp BETWEEN DATE_SUB(NOW, INTERVAL 1 DAY)
AND NOW()
GROUP BY t.id) x ON x.id = a.id
ORDER BY x.num DESC
Try:
Select b.ColA, b.ColB, b.ColC,-- etc.
Count(*) count
From TableB b
Join TableA a
On a.Id = b.Id
And a.TimeStamp > getDate() - 1
Group By b.ColA, b.ColB, b.ColC -- etc.
Order By Count(*) Desc
If you also want to see the rows from TableB that have no timestamps in the past 24 hours then use an outer join:
Select b.ColA, b.ColB, b.ColC,-- etc.
Count(*) count
From TableB b
Left Join TableA a
On a.Id = b.Id
And a.TimeStamp > getDate() - 1
Group By b.ColA, b.ColB, b.ColC -- etc.
Order By Count(*) Desc