来自3个不同表的SQL查询

时间:2014-02-13 16:17:13

标签: mysql sql

共有3个表格:

 Users table
 ------------
|uid|username|
 ------------ 

    Values table
 ------------------
|vid|values|checked|
 ------------------

  Relations
 -----------
|cid|uid|vid|
 -----------

“关系”表包含与值ids相关的用户ID。如何从值表中选择与关系表中给定用户ID无关的值id?

修改

到目前为止我尝试了什么:

SELECT vid FROM relations where uid=user_id //this gives me array of value ids
SELECT vid FROM values where vid!=vid1 AND vid!=vid2 .....

EDIT2: 可以找到基本解决方案here。但是有更有效的方法吗?如果表格对于值表和关系表都非常大,则基本解决方案效率不高。

6 个答案:

答案 0 :(得分:1)

您使用的是哪个dbms?它是否支持减号条款?如果是,你可以做这样的事情

    select vid from values 
    minus
    select vid from relations where uid = @user_id

这应该给出未映射到给定用户ID的视频

另一种方法是通过not-exists子句(如果dbms不支持minus子句,则很方便)

    select v.vid from values v where not exists (select 1 from relations r where 
    r.vid = v.vid and r.user_id = @user_id)

我会警告不要使用not in子句。它的性能是有问题的,如果内部查询返回一个空值,则会失败,虽然在你的情况下是不可能的,但是你应该养成一个习惯,永远不要在子查询中使用'not in'子句。只有当你有一个文字值列表时才使用它,例如'... vid不在(1,2,3,4)'。每当你必须根据另一个表中的值从一个表中“减去”某些内容时,使用“不存在”并且永远不会“不存在”

答案 1 :(得分:0)

你可以吗?

select vid from values where vid not in (select vid from relations where uid = user_id)

答案 2 :(得分:0)

我认为像这个查询这样的简单就足够了。

如果值表中的特定条目没有uid,则关系表中也不应该有条目。

SELECT vid
FROM values
LEFT JOIN relations on values.vid = relations.vid
WHERE relations.uid IS NULL

答案 3 :(得分:0)

select distinct v.vid
from values v
left join relations r on (r.vid=v.vid)
where r.uid != user_id

遗憾的是,MySQL不支持with;不幸的是,这不会很好。

答案 4 :(得分:0)

如果您的“关系”表中的值恰好是0或1次,则可以使用JOIN

SELECT `Values`.`vid` FROM `Values`
LEFT JOIN `Relations` ON (`Values`.`vid` = `Relations`.`vid`)
WHERE `Relations`.`uid` != 1;

如果Value在Relations表中的次数超过1次,则无法使用,因为在这种情况下WHERE会匹配另一行与其他uid不同的行。与NOT IN相同,这也可以匹配具有相同视频的另一行但是另一个uid。

如果在Relation表中每个Value至少有一次,那么最有效的方法是只查询Relations表:

SELECT DISTINCT `Relations`.`vid` FROM `Relations`
WHERE `Relations`.`uid` != 1;

如果在“关系”表中值可以是0,1或更多次,最好的方法是使用EXISTS(另请参阅taimur的答案):

SELECT `Values`.`vid` FROM `Values`
WHERE NOT EXISTS (
  SELECT * FROM `Relations`
  WHERE `Relations`.`vid` = `Values`.`vid` AND `Relations`.`uid` = 1
);

但是,EXISTSINJOIN慢一点,因此您应该比较执行时间的情况。

答案 5 :(得分:0)

我认为您可以执行这样的简单查询(假设用户标识符的数据类型为int):

DECLARE @givenUserID int --local variable where you store the given user identifier

SELECT vid
FROM Values
WHERE vid NOT IN (SELECT vid FROM Relations where uid = @givenUserID)