我有三张桌子:
订单
orderID
userID
用户
userID
lastViewedOrderID
votehistory
userID
orderID
我有一个PHP函数:getOrdersForUser($userID)
,它应该返回一组具有以下条件的orderID值:
1)用户尚未查看订单(orders.orderID> users.lastViewedOrderID)
2)被查询的用户没有下订单(orders.userID!= users.userID)
3)该用户未根据投票历史表投票(orderID不在投票历史中,其中userID = [传递的用户ID值])
到目前为止,我提出的最好的是:
SELECT orders.orderID
FROM orders
JOIN users
ON users.userID != orders.userID
JOIN votehistory
ON (votehistory.userID = users.userID) AND (votehistory.orderID != orders.orderID )
WHERE users.userID = [the userID value passed in]
AND orders.orderID > users.lastViewedOrderID
AND likehistory.orderID != orders.orderID
不幸的是,这给了我大量的重复 - 对于投票历史中的每个有效行重复相同的orderID。我似乎不明白JOIN过程是如何优化的。我是否应该尝试减少通过子查询加入的表中的行数?排除重复项的最有效方法是什么?
答案 0 :(得分:1)
因为您只想要orderID,所以可以使用EXISTS
来执行此操作。像这样:
SELECT orders.orderID
FROM orders
WHERE EXISTS
(
SELECT NULL
FROM users
JOIN votehistory
ON (votehistory.userID = users.userID)
WHERE users.userID != orders.userID
AND users.userID = [the userID value passed in]
AND (votehistory.orderID != orders.orderID )
AND orders.orderID > users.lastViewedOrderID
AND likehistory.orderID != orders.orderID
)
参考:
答案 1 :(得分:0)
添加几个索引后,我发现此查询可以高效工作:
SELECT orders.orderID
FROM orders
WHERE orders.orderID NOT IN
(
SELECT votehistory.orderID
FROM users
JOIN votehistory
ON (votehistory.userID = users.userID)
WHERE users.userID = [userID input value]
)
AND orders.userID != [userID input value]
AND orders.orderID >
(
SELECT lastViewedOrderID
FROM users
WHERE userID = [userID input value]
)
ORDER BY orders.orderID ASC