有没有办法在这种类型的SQL SELECT中删除嵌套查询?

给定这个表结构和示例数据(t3不应该在查询中使用,它只是在这里显示t1和t2之间的关系):
      t1                 t2                         t3
--------------   -----------------   --------------------------------
| id | value |   | t1key | t3key |   | id | value                   |
|  1 |  2008 |   |     3 |     1 |   |  1 | "New intel cpu in 2010" |
|  2 |  2009 |   |     4 |     1 |   |  2 | "New amd cpu in 2008"   |
|  3 |  2010 |   |     6 |     1 |   |    |                     ... |
|  4 | intel |   |     1 |     2 |   --------------------------------
|  5 |   amd |   |     5 |     2 |
|  6 |   cpu |   |     6 |     2 |
|    |   ... |   |       |   ... |
--------------   -----------------
您将如何构建满足以下条件的SQL查询:
Given the input for t1.id is the set {6} returns t1.id set {3,4,6,1,5}
Given the input for t1.id is the set {6,4} returns t1.id set {3,4,6}
Given the input for t1.id is the set {5,4} returns t1.id set {}
当桌子更大时,不会扼杀性能......?     
已邀请:
你想要什么并不是很清楚。 我将呼叫表t1
word
,呼叫表t3
phrase
并呼叫表t2
word is in phrase
。 然后我猜你想要找到与一组特定word.ids在同一短语中的所有word.ids。那是对的吗?
SELECT DISTINCT t1.id
FROM t1 
  JOIN t2
    ON t1.id = t2.t1key
  JOIN t2 copyt2
    ON copyt2.t3key = t2.t3key 
WHERE copyt2.t1key IN
  (6,4)       --what you want to check here
更正 阅读Joe的评论并重新阅读问题详细信息,我想您希望找到所有出现在同一短语中的单词,并在指定列表中显示所有单词。 这看起来像一个关系划分问题:
SELECT DISTINCT t2a.t1key
FROM t2 AS t2a
WHERE NOT EXISTS
  ( SELECT *
    FROM t2 AS t2b
    WHERE t2b.t1key IN (6,4)
      AND NOT EXISTS
      ( SELECT *
        FROM t2 AS t2c
        WHERE t2a.t3key = t2c.t3key
          AND t2c.t1key = t2b.t1key
      )
  )
第二解决方案
SELECT a.t1key
FROM t2 AS a
  JOIN t2 as b
    ON  a.t3key = b.t3key
WHERE b.t1key IN (6,4)       --list you want to check
GROUP BY a.t1key, a.t3key
HAVING COUNT(*) = 2          --size of list
;
第三解决方案
SELECT DISTINCT t1key
FROM t2
WHERE t3key IN
  ( SELECT t3key
    FROM t2
    WHERE t1key IN (6,4)
    GROUP BY t3key
    HAVING COUNT(*) = 2
  )
;
注意:第一个(使用
NON EXISTS
)解决方案与其他两个解决方案有很大不同: 如果你尝试使用列表,其成员没有出现在表t2中,比如说
(2)
(2,7)
,它将显示来自t2的所有t1key。 在这种情况下,第二和第三解决方案将完全显示NO键。     
这是我的杰出贡献(至少让我们假设它现在很棒:)
SELECT DISTINCT a2.t1key, COUNT( * ) AS cnt
FROM t2 AS a1
    LEFT JOIN t2 AS a2 ON a2.t3key = a1.t3key
WHERE a1.t1key IN ( 6, 4 ) 
GROUP BY a2.t3key, a2.t1key
HAVING cnt >=2
IN (6,4)
部分真的是自我解释。在
cnt >=2
2中是
IN
子句中
id
-s的数量。例如:你使用的是
IN (6)
,那么你应该使用
cnt >=1
。 我不确定
>
是否需要,但是我很懒,不能创建一个更大的数据集来测试:)     
select distinct t1key
from t2
where t3key in
(
    select t3key from t2 where t1key = 6
    intersect
    select t3key from t2 where t1key = 4
)

==> 3, 4, 6
您需要添加更多“交叉”子句,具体取决于输入集中的项目数。 在SQL Server上测试过。     
select distinct t2b.t1key
from 
  t2 t2a
  inner join t2 t2b on t2a.t3key = t2b.t3key
where t2a.t1key in (6, 5) /* or whatever */
从t1(关键字)开始,您将获得包含“cpu”(或其他)的所有t3(表达式)。您不需要直接加入t3,也不需要任何数据。第二次加入t2,您将获得找到的表达式中包含的所有其他关键字。你只需要返回它们的t1key。 更正:如果您不想要子查询,可以为每个要搜索的关键字创建一个连接:
select distinct t2b.t1key
from 
  t2 t2a
  inner join t2 t2b on t2a.t3key = t2b.t3key and t2a.t1key = 6
  inner join t2 t2c on t2a.t3key = t2c.t3key and t2a.t1key = 5
    
他在那里, 你确定你选择了正确的桌子结构吗? 它似乎没有规范化 - 虽然我不确切知道每个表可以代表什么实体。 保持数据库设计至少是第三种正常形式很重要(参见维基百科文章 您的查询将更自然,更容易制定     

要回复问题请先登录注册