【问题标题】:Can we replace nested sub-queries with joins - SQL我们可以用连接替换嵌套的子查询吗 - SQL
【发布时间】:2018-07-20 09:54:08
【问题描述】:

目前我们正在使用以下嵌套查询来获取特定结果。查询给了我正确的结果,但问题是它需要更多的时间来执行(大约 2 秒来获取 9 条记录)。表中的记录:

Table      |  Number of Records
-------------------------------
Account          284
AccountUser       34
AccountCustomer  256
AccountGroup      96

以下是我的查询:

SELECT * FROM Account  where (SomeID = 'XXXXX-XXXXX-XXXXX') and  AccountID  IN  
(SELECT AccountID   FROM AccountUser WHERE SomeID = 'XXXXX-XXXXX-XXXXX' AND AccountID IN  
(SELECT AccountID   FROM AccountCustomer WHERE SomeID = 'XXXXX-XXXXX-XXXXX' AND isDeleted = 0  AND someOtherID IN 
(SELECT someOtherID FROM AccountGroup   WHERE AccountGroupID = 'YYYY-YYYYY-YYYY' AND AccountGroup.SomeID = 'XXXXX-XXXXX-XXXXX' AND AccountID NOT IN  
(SELECT AccountID   FROM AccountGroup WHERE AccountGroupID = 'YYYY-YYYYY-YYYY' AND AccountGroup.SomeID = 'XXXXX-XXXXX-XXXXX'))))

我认为联接会提供更好的性能(如果我错了请纠正我),因此用联接替换了嵌套查询,但它没有给我预期的结果。加入查询如下:

SELECT a.* FROM Account a
Inner join AccountUser b on a.AccountID = b.AccountID
Inner join AccountCustomer c on c.AccountID = a.AccountID 
Inner join AccountGroup d on d.AccountID = a.AccountID 
Inner join AccountGroup e on e.AccountID = a.AccountID 
WHERE a.SomeID = 'XXXXX-XXXXX-XXXXX' and 
      b.SomeID = 'XXXXX-XXXXX-XXXXX' and 
      c.SomeID = 'XXXXX-XXXXX-XXXXX' and 
      c.isDeleted = 0 and d.AccountGroupID = 'YYYY-YYYYY-YYYY' and
      d.SomeID = 'XXXXX-XXXXX-XXXXX' and
      e.AccountGroupID ='YYYY-YYYYY-YYYY'

谁能告诉我查询中连接的构造有什么问题。

【问题讨论】:

  • 显示一些示例数据以及您当前和预期的输出将非常有帮助。
  • @TimBiegeleisen:抱歉无法分享真实数据,为所有表格创建这些示例数据需要很长时间,无论如何我会尝试。
  • 将子查询替换为连接时的一个可能差异是,当您确实有 1-n 或 n-m 关系并且连接使第一表行“重复”时

标签: sql sql-server join subquery sqlperformance


【解决方案1】:

试试这个

SELECT distinct a.* FROM Account a
Inner join AccountUser b on a.AccountID = b.AccountID
Inner join AccountCustomer c on c.AccountID = a.AccountID 
Inner join AccountGroup d on d.someOtherID = c.someOtherID 
WHERE a.SomeID = 'XXXXX-XXXXX-XXXXX' and 
      b.SomeID = 'XXXXX-XXXXX-XXXXX' and 
      c.SomeID = 'XXXXX-XXXXX-XXXXX' and 
      c.isDeleted = 0 and d.AccountGroupID = 'YYYY-YYYYY-YYYY' and
      d.SomeID = 'XXXXX-XXXXX-XXXXX' and
      d.AccountID  not in 
(SELECT AccountID   FROM AccountGroup WHERE AccountGroupID = 'YYYY-YYYYY-YYYY' AND AccountGroup.SomeID = 'XXXXX-XXXXX-XXXXX')

【讨论】:

  • 修复了我在使用 distinct a.* 而不是 a.* 时遇到的问题。
【解决方案2】:

我可以找到两个问题。

  1. 列名错误

    isDeleted = 0 更改为 c.isRelated = 1

  2. 连接d和e的错误子句

    且 AccountID 不在

【讨论】:

  • 对不起兄弟,isDeletedisRelated 是错误的,即使更改后结果相同
【解决方案3】:
Inner join AccountGroup d on d.AccountID = a.AccountID 

应该是

Inner join AccountGroup d on d.someOtherID = a.AccountID 

?

【讨论】:

    【解决方案4】:

    除了使用 JOIN,您还可以考虑使用 WHERE EXISTS 或 WHERE NOT EXISTS 来代替丑陋的 IN 语句。连接有时返回的行数可能比使用 IN 语句检索到的行数多。从查询中我看到您只需要帐户表中的数据,因此 EXISTS 似乎是更合乎逻辑的方法。

    【讨论】:

    • 你能举个例子吗?我之前没用过WHERE EXISTS
    猜你喜欢
    • 2023-02-25
    • 1970-01-01
    • 1970-01-01
    • 2014-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多