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

发布于 2024-10-27 14:53:25 字数 985 浏览 1 评论 0原文

给定此表结构和示例数据(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 {}

并且不会影响性能当桌子更大时......?

Given this table structure and example data (t3 should not be used in the query, it is only here to show the relation between t1 and 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 |
|    |   ... |   |       |   ... |
--------------   -----------------

How would you build a SQL query that would satisfy the following:

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 {}

and doesn't kill performance when the tables are bigger...?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

自在安然 2024-11-03 14:53:25

这是我的出色贡献(至少让我们假设它现在很出色:)

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

我不确定是否需要 > ,但我很懒,没有创建更大的数据集来测试:)

Here is my brilliant contribution (at least let's assume it's brilliant for now:)

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

The IN (6,4) part is really self explanatory. In the cnt >=2 2 is the number of id-s in the IN clause. For example: you're using IN (6) then you should use cnt >=1.

I'm not sure > is needed at all, but I am lazy enogh not to create a larger dataset to test on :)

有木有妳兜一样 2024-11-03 14:53:25

不太清楚你想要什么。

我将调用表 t1 word,调用表 t3 phrase 并调用表 t2 word is inphrase

那么我猜你想找到与一组特定的 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

更正

阅读乔的评论并重新阅读问题详细信息,我猜您想找到与指定列表中的所有单词出现在同一短语中的所有单词。

这看起来像一个关系除法问题:

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。

在这种情况下,第二个和第三个解决方案将根本不显示任何密钥。

It's not very clear what you want.

I will call table t1 word, call table t3 phrase and call table t2 word is in phrase.

Then I guess you want to find all word.ids that are in a same phrase as a specific set of word.ids. Is that correct?

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

CORRECTION

Reading Joe's comment and re-reading the question details, I guess you want to find all words that appear in same phrase with ALL words in your specified list.

This looks like a relational division problem:

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
      )
  )

2nd solution:

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
;

3rd solution:

SELECT DISTINCT t1key
FROM t2
WHERE t3key IN
  ( SELECT t3key
    FROM t2
    WHERE t1key IN (6,4)
    GROUP BY t3key
    HAVING COUNT(*) = 2
  )
;

Note: The first (with NON EXISTS) solution has a great difference with the other two:

If you try it with a list that its members do not appear in table t2, say (2) or (2,7), it will show ALL t1key's from t2.

The 2nd and 3rd solutions will show NO keys at all in such a case.

香橙ぽ 2024-11-03 14:53:25
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 t1key
from t2
where t3key in
(
    select t3key from t2 where t1key = 6
    intersect
    select t3key from t2 where t1key = 4
)

==> 3, 4, 6

You would need to add more "intersect" clauses depending on how many items are in your input set.

Tested on SQL Server.

叫思念不要吵 2024-11-03 14:53:25
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
select distinct t2b.t1key
from 
  t2 t2a
  inner join t2 t2b on t2a.t3key = t2b.t3key
where t2a.t1key in (6, 5) /* or whatever */

Starting on t1 (the keyword), you get all the t3 (expressions) which contain "cpu" (or whatever). You don't need to join t3 directly, you don't need any data from there. Joining t2 a second time you get all other keywords which are contained in the found expressions. You only need to return the t1key's of them.


Correction: If you don't want subqueries, you could create a join for each keyword to search for:

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
骷髅 2024-11-03 14:53:25

他在那里,
您确定选择了正确的表结构吗?
它似乎没有标准化 - 尽管我不确切知道每个表可以代表什么实体。

保持数据库设计至少采用第三范式非常重要(请参阅维基百科文章

您的查询将更加自然且易于配制

He there,
Are you sure you have chosen the right table structure?
It doesn't seem to be normalized - though I don't know exactly what entity each table could represent.

Its important to keep your database design at least in the third normal form (see Wikipedia article

Your queries will be much more natural and easily formulated

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文