我不是数据库专业人员,但目前正在处理一个查询(PHP->MySQL):
我有3张桌子:
"项目":id,名称,链接
"ItemsToUsers":id,item_id,user_id
"用户":id,电子邮件
每个"项目"的可用性都会定期进行更改,我会通过一些算法进行实时检查。
我的目标是
1) 选择所有项目并在飞行中检查它们是否可用
2) 如果项目可用,请通过电子邮件通知正在监视它的用户。为此,我需要从"ItemsToUsers"中选择用户,然后从"users"表中获取他们的电子邮件。
我知道如何用一种简单的方式来做,但我觉得我会遇到很多查询。(每个用户单独选择…)
有没有一种方法可以更有效地做到这一点:在一个查询中还是通过更改算法?感谢您抽出时间!
没有足够的信息来确定项目的可用性。这严重阻碍了查询项目2的能力。
也就是说,让我们假设我们向Items表添加一个"可用"列,该列为0表示不可用,1表示可用。
那么,一个查询可以获得观看可用项目的人的所有电子邮件地址,它是:
SELECT u.email FROM Users AS u JOIN ItemsToUsers AS k ON k.user_id = u.id JOIN Items AS i on i.id = k.item_id WHERE i.available = 1;
或者,您可以使用子查询和IN.
假设您有一个名为Availability的不同表,其列为id、item_id和available,这也是一个tinyint,其中包含1表示可用,0表示不可用。
SELECT u.email FROM Users AS u JOIN ItemsToUsers AS k ON k.user_id = u.id WHERE k.item_id IN (SELECT a.item_id FROM Availability AS a WHERE a.available = 1);
同样,如果不知道如何获得可用产品列表,就不可能优化查询以检索电子邮件地址列表。
您的步骤暗示在n+1个查询中执行此操作(其中n=Items表中的条目数):
SELECT * FROM Items; -- This is the +1 part
在迭代该结果集时,您打算确定它是否可用,如果可用,则通知正在观看它的用户。假设您有一个给定的项目id,并且如果该产品id是活动的,则您希望选择所有用户的电子邮件,那么您可以这样做:
SELECT email FROM Users u
INNER JOIN ItemsToUsers iu ON iu.user_id = u.id
INNER JOIN Items i ON iu.item_id = i.id
WHERE i.id = {your item id}
您将对表中的每个项运行此查询。这是n部分。
通常,您可以为正在观看所有活动产品的所有用户生成电子邮件列表,在之后,您已经确定哪些产品应该处于活动状态:
SELECT DISTINCT email FROM Users u
INNER JOIN ItemsToUsers iu ON iu.user_id = u.id
INNER JOIN Items i ON iu.item_id = i.id
WHERE i.is_active = 1
这将在总共2个查询中完成任务,无论您有多少用户或项目。作为奖励,这个解决方案可以为您提供不同的电子邮件,而第一个解决方案仍然需要应用程序级别的代码来删除多个查询返回的重复邮件。
SELECT Items.id, Items.name, Items.link FROM Items
INNER JOIN ItemsToUsers ON ItemsToUsers.item_id = Items.items.id
INNER JOIN Users ON ItemsToUsers.user_id = Users.id ;