How to write sql for this?

泪湿孤枕 提交于 2019-12-13 08:23:54

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!