项目 - Id,Name,
PurchaseLog - Id,ItemId,CustomerId,PurchaseDate
用户 - ID,用户名
对于给定的两个客户的用户名,找到他们去年购买的普通商品的名称。
这是天真(甚至是正确的)吗? :
select distinct item.id, item.name
from item i, PurchaseLog log_username1, PurchaseLog log_username2, user user1, user user2
where lower(user1.username) = lower('UserName1') AND
lower(user2.username) = lower('UserName2') AND
log_username1.itemid = log_username2.itemid AND
log_username2.itemid = i.itemid AND
log_username1 >-- satisfy date contraint AND
log_username2 >-- satisfy date contraint
答案 0 :(得分:8)
您描述了交叉点查询的基本要求。
select item.id, item.name
from item, PurchaseLog p, user u
where lower(u.username) = lower('Username1')
AND p.user_id = u.user_id
and item.id = p.itemid
and p.purchasedate between SYSDATE and SYSDATE-365
INTERSECT
select item.id, item.name
from item, PurchaseLog p, user u
where lower(u.username) = lower('Username2')
AND p.user_id = u.user_id
and item.id = p.itemid
and p.purchasedate between SYSDATE and SYSDATE-365
这将返回为两个用户显示的item.id和item.name列表。
答案 1 :(得分:0)
此解决方案使用半连接,在您的情况下应该是最佳的,因为它不需要在结果上有明显区别。 / + inline / hint告诉优化器不要在user_items子查询上使用临时表。为了提高性能,你应该使用一个列(一个虚拟列应该是最佳的),user.userid被限制为小写并在其上使用索引,所以以后你不需要在它上面调用较低的。
我还认为您错过了在查询中指定PurchaseLog和用户表之间的连接条件。
with user_items as (
select /*+inline*/ lower(username),itemid
from PurchaseLog
join user using (userid) /*you were missing this join in your query*/
where log_username >-- satisfy date contraint
)
select item.id, item.name
from item i
where itemid in (
select itemid
from user_items
where username = lower('UserName1')
) and itemid in (
select itemid
from user_items
where username = lower('UserName2')
)
/