嵌套加入子查询和失败的关联

时间:2015-06-04 18:11:31

标签: mysql sql join subquery

我有3个表sc_user,sc_cube,sc_cube_sent

我想加入一个用户查询(sc_user)一个不同的随机消息/多维数据集(来自sc_cube),之前尚未发送给该用户(sc_cube_sent),因此结果集中的每一行都有一个不同的用户ID以及来自sc_cube的随机cubeid,它不是sc_cube_sent的一部分,并且该用户ID与之关联。

我面临的问题是,我似乎无法在内部On子句中使用外部查询的u.id的情况下使用相关ID。我需要注释部分才能使它工作。

# get one random idcube per user not already sent to that user
SELECT u.id, sub.idcube
FROM sc_user as u
LEFT JOIN (
    SELECT c.idcube, sent.idreceiver FROM sc_cube c
    LEFT JOIN sc_cube_sent sent ON ( c.idcube = sent.idcube /* AND sent.idreceiver = u.id <-- "unknown column u.id in on clause" */  )
WHERE sent.idcube IS NULL
ORDER BY RAND()
LIMIT 1
) as sub
ON 1

我添加了一些数据:http://sqlfiddle.com/#!9/7b0bc/1 应该为用户1显示的新立方体(sc_cube)如下:2150,2151,2152,2153

编辑&gt;&GT;

我可以使用另一个子查询而不是连接来实现它,但这会产生巨大的性能影响,并且不可行(每个表上有几千行,并且使用合理实现的键,每行数为30秒),所以我仍然在寻找通过JOIN使用解决方案的方法。

SELECT
u.id,
(SELECT sc_cube.idcube
FROM sc_cube
WHERE NOT EXISTS(
      SELECT sc_cube.idcube FROM sc_cube_sent WHERE sc_cube_sent.idcube = sc_cube.idcube AND sc_cube_sent.idreceiver = u.id
)
ORDER BY RAND() LIMIT 0,1
) as idcube
FROM sc_user u

3 个答案:

答案 0 :(得分:0)

无法测试这个,我会说你需要在子查询中包含sc_user,因为你已经丢失了范围

LEFT JOIN 
(   SELECT c.idcube, sent.idreceiver 
    FROM sc_user u
    JOIN sc_cube c ON c.whatever_your_join_column_is = u.whatever_your_join_column_is
    LEFT JOIN sc_cube_sent sent ON ( c.idcube = sent.idcube AND sent.idreceiver = u.id  )
    WHERE sent.idcube IS NULL
    ORDER BY RAND()
    LIMIT 1
) sub

答案 1 :(得分:0)

如果您想获得尚未发送给特定用户的消息标识,那么为什么要使用加入或左连接呢?
只是做:

SELECT sent.idcube 
FROM sc_cube_sent sent 
WHERE sent.idreceiver <> u.id

然后查询可能如下所示:

SELECT u.id, 
       /* sub.idcube */
      (  SELECT sent.idcube 
         FROM sc_cube_sent sent 
         WHERE sent.idreceiver <> u.id
         ORDER BY RAND()
         LIMIT 1
      ) as idcube
FROM sc_user as u

答案 2 :(得分:0)

在on子句中使用NOT IN subselect。虽然在LEFT JOIN范围内没有给出相关链接u.id,但它是ON子句的范围。以下是它的工作原理:

SELECT u.id, sub.idcube
FROM sc_user as u
LEFT JOIN ( 
     SELECT idcube FROM sc_cube c ORDER BY RAND()
) sub ON ( 
  sub.idcube NOT IN ( 
     SELECT s.idcube FROM sc_cube_sent s WHERE s.idreceiver = u.id
  ) 
)
GROUP BY u.id

小提琴:http://sqlfiddle.com/#!9/7b0bc/48