问题
I've tables like this
Customer
-ID
-name
-address
Business
-ID
-name
-type
Discount
-ID
-amount
-BusinessID
-position
UsedDiscounts
-CustomerID
-DiscountID
Business has many discounts.
User has used many discounts, record of which is in UsedDiscounts.
User can only use discount in order, defined by position. Discount 1, then Discount 2. So even if business has 10 discounts out, the one Customer qualifies for is Position of used discount by that business + 1.
Goal: get all discounts user qualify for.
My approach was to do left exclusion join on Discounts and Used Discounts.
So get all discounts minus used ones, then somehow do min on position and get all "qualified" ones. However, I might be able to pull this off in SQL I have no idea how..
Sample Incomplete SQL looks like this
SELECT *, min(gd.position) FROM
(SELECT * FROM "Deals" as d WHERE (d.active = true) AND (d.latitude BETWEEN 40 AND 41) AND (d.longitude BETWEEN -75 AND -70)) AS gd
LEFT JOIN
(SELECT du."DealId" FROM "DealsUsed" AS du WHERE du."CustomerId" = 1) AS bd
ON gd.id = bd."DealId"
WHERE bd."DealId" IS NULL
GROUP BY gd."UserId";
gives wrong output
Sample data:
Customer
--------
id name address
0 Tobby 93903903
1 Emi 3839039
2 Loop 393030
Business
--------
id name type
0 Cool flower
1 Corner car
2 New deli
3 Side printing
4 Big car
Discount
--------
id amount businessId position
0 10 0 0
1 22 3 1
2 10 3 2
3 43 2 0
4 23 5 0
5 10 5 1
Used Discount
----------
customerId discountId
1 2
outcome for customer 1 , emi, shouuld be
Discounts
--------
id amount businessId position
0 10 0 0
4 23 5 0
3 43 2 0
5 10 5 1
回答1:
Your left join does not take affect because you use where clause in the second query:
Remove where clause:
SELECT *, min(gd.position) FROM
(SELECT * FROM "Deals" as d WHERE (d.active = true) AND (d.latitude BETWEEN 40 AND 41) AND (d.longitude BETWEEN -75 AND -70)) AS gd
LEFT JOIN
(SELECT du."DealId" FROM "DealsUsed" AS du) AS bd
ON gd.id = bd."DealId"
WHERE bd."DealId" IS NULL
GROUP BY gd."UserId";
using Group by with Select * is not advisable. Just select the fields you need. Something like:
SELECT gd."UserId", min(gd.position) FROM
(SELECT * FROM "Deals" as d WHERE (d.active = true) AND (d.latitude BETWEEN 40 AND 41) AND (d.longitude BETWEEN -75 AND -70)) AS gd
LEFT JOIN
(SELECT du."DealId" FROM "DealsUsed" AS du) AS bd
ON gd.id = bd."DealId"
WHERE bd."DealId" IS NULL
GROUP BY gd."UserId";
You can use where clause after on like:
SELECT gd."UserId",bd."CustomerId", min(gd.position) FROM
(SELECT * FROM "Deals" as d WHERE (d.active = true) AND (d.latitude BETWEEN 40 AND 41) AND (d.longitude BETWEEN -75 AND -70)) AS gd
LEFT JOIN
(SELECT du."DealId" FROM "DealsUsed" AS du) AS bd
ON gd.id = bd."DealId"
WHERE bd."DealId" IS NULL and bd."CustomerId" = 1
GROUP BY gd."UserId";
来源:https://stackoverflow.com/questions/49137542/how-to-write-sql-for-this