Reputation: 327
I am trying to query a receipts table, to pull order numbers from a database who's first transaction falls within a certain time range. Here is what I have so far:
SELECT id, order_number,
(
SELECT id FROM receipts
WHERE received < r.received AND order_number = r.order_number
LIMIT 1
) priorPayment
FROM receipts r
WHERE received > 1416384000 AND received < 1416470399
ORDER BY id DESC
This works fine except I want to filter out anything that has a priorPayment returned (so only show where this subquery returns null) right now it returns everything. Any suggestions?
Upvotes: 0
Views: 4478
Reputation: 1270583
Although you can use a subquery for this or a having
clause, I would recommend simply using a left join
SELECT r.id, r.order_number
FROM receipts r LEFT JOIN
receipts r2
ON r2.received < r.received and r2.order_number = r.order_number
WHERE r.received > 1416384000 AND r.received < 1416470399 AND
r2.order_number is NULL
ORDER BY r.id DESC;
Upvotes: 3
Reputation: 53870
Here's a common way to write that:
SELECT r.id, r.order_number
FROM receipts r
WHERE r.received > 1416384000 AND r.received < 1416470399
AND NOT EXISTS (SELECT id FROM receipts WHERE received < r.received AND order_number = r.order_number LIMIT 1)
ORDER BY r.id DESC
Alternatively, you can use an anti-join in this case:
SELECT r1.id, r1.order_number
FROM receipts r1
LEFT JOIN receipts r2
ON r2.order_number = r1.order_number AND r2.received < r1.received
WHERE r1.received > 1416384000 AND r1.received < 1416470399
AND r2.order_number is NULL
ORDER BY r1.id DESC
Upvotes: 1
Reputation: 427
For better performance I would recommand to keep the sub-query (which selects only the 3 columns you need) and combine it, with the LEFT JOIN and the IS NULL condition to get the expected result:
SELECT r.id, r.order_number
FROM receipts r
left join (
SELECT id, received, order_number FROM receipts
) priorPayment
ON priorPayment.received < r.received
AND priorPayment.order_number = r.order_number
WHERE r.received > 1416384000
AND r.received < 1416470399
AND r.priorPayment.id is null
ORDER BY r.id DESC
Upvotes: 1
Reputation: 7890
another way is just bring the subquery
from select
into where
clause:
SELECT id, order_number, null as priorPayment
FROM receipts r
WHERE received > 1416384000 AND received < 1416470399
and (
SELECT id FROM receipts
WHERE received < r.received AND order_number = r.order_number
LIMIT 1
) is null
ORDER BY id DESC
Upvotes: 1