查询中查询:有没有更好的办法?(Queries within queries: Is there a

2019-09-27 01:30发布

当我建立更大,更先进的Web应用程序,我发现自己写很长的和复杂的查询。 我倾向于在查询中编写查询了很多,因为我觉得自己做的数据库一个呼叫从PHP是不是让数和数据关联更好。

然而,谁知道什么SQL谁知约JOIN秒。 就个人而言,我已经使用了JOIN或前二,但是当我发现使用子查询很快停止,因为它觉得更方便,快捷的为我编写和维护。

通常情况下,我会做,可能包含来自相关表的一个或多个子查询的子查询。
考虑下面这个例子:

SELECT 
  (SELECT username FROM users WHERE records.user_id = user_id) AS username,
  (SELECT last_name||', '||first_name FROM users WHERE records.user_id = user_id) AS name,
  in_timestamp,
  out_timestamp
FROM records
ORDER BY in_timestamp

少数情况下,我会在以后做的子查询WHERE子句。
考虑下面这个例子:

SELECT
  user_id,
  (SELECT name FROM organizations WHERE (SELECT organization FROM locations WHERE records.location = location_id) = organization_id) AS organization_name
FROM records
ORDER BY in_timestamp

在这两种情况下,我会看到任何形式的进步,如果我决定用一个重写查询JOIN

随着越来越多的毯子问题,什么是使用子查询或优势/劣势JOIN ? 是一种方法更正确或比其他接受?

Answer 1:

连接是优选的以分离[子]查询。
如果子选择(AKA子查询)不相关的外部查询,这是非常有可能的优化器将扫描表(S)的子查询一次,因为该值是不可能改变的。 当你有关系,就像在所提供的示例中,单次优化的可能性变得不太可能。 在过去,它被认为相关子查询执行,RBAR - 连续被折腾行。 用JOIN,能够在确保在表中的单个通来实现相同的结果。

这是提供查询的正确重写:

   SELECT u.username,
          u.last_name||', '|| u.first_name AS name,
          r.in_timestamp,
          r.out_timestamp
     FROM RECORDS r 
LEFT JOIN USERS u ON u.user_id = r.user_id
 ORDER BY r.in_timestamp

......因为子查询可以返回NULL,如果USER_ID不在存在USERS表。 否则,你可以使用一个INNER JOIN:

  SELECT u.username,
         u.last_name ||', '|| u.first_name AS name,
         r.in_timestamp,
         r.out_timestamp
    FROM RECORDS r 
    JOIN USERS u ON u.user_id = r.user_id
ORDER BY r.in_timestamp

派生表/内嵌视图还可以通过使用JOIN语法。



Answer 2:

在简单的情况下,查询优化器应该能够产生相同的计划,一个简单连接与一个简单的分选。

但在一般情况(在适当情况下),你应该有利于加入了子选择。

此外,应避免相关子查询(其中内表达指的是外的查询),因为它们是有效的for循环在for循环内)。 在大多数情况下,相关子查询可以写成一个连接。



Answer 3:

一)我想通过指出的是,两者并不一定是可以互换的开始。 嵌套因为你已经要求那里是0或1的匹配值,否则,你会得到一个错误。 联接看跌期权没有这样的要求,可以排除该记录或引进更多的取决于您的数据和连接的类型。

b)在性能方面,则需要检查查询计划,但您的嵌套的例子不太可能是更有效的比表连接。 通常,子查询每行执行一次但这在很大程度上取决于你的数据库,唯一约束,foriegn键,不为空等等也许DB可以更有效地重写上,但连接可以使用更广泛的技术,推动来自不同数据表等,因为他们做不同的事情(虽然你可能不取决于你的数据在输出中观察到的任何差异)。

C)大多数DB意识到程序员,我知道会看你的嵌套查询和重写使用联接,受制于数据是合适的“干净”。

d)关于“正确” - 我赞成联接您的数据备份与正确的约束条件在必要时(如一个唯一的用户ID)。 你作为一个人可以做出某些假设,但DB引擎不能,除非你告诉它。 它知道的越多,更好的工作它(和你)可以做。



Answer 4:

加入在大多数情况下,将更加快捷。

让我们用一个例子。

让我们用你的第一个查询:

SELECT 
(SELECT username FROM users WHERE records.user_id = user_id) AS username,
  (SELECT last_name||', '||first_name FROM users WHERE records.user_id = user_id) AS name,
  in_timestamp,
  out_timestamp
FROM records
ORDER BY in_timestamp

现在考虑我们有100条记录中记录和100条记录的用户。(假设我们没有对user_ID的指数)

因此,如果我们理解你的算法,它说:对于每个记录扫描所有100个记录的用户找出用户名扫描所有100个记录的用户找出姓氏和名字

因此,它就像我们扫描用户表100 * 100 * 2的时间。 是否真的值得。 如果我们考虑USER_ID它会使事情更好的指标,但它仍然是值得的。

现在考虑一个连接(嵌套循环几乎会产生相同的结果同上,但考虑散列连接):它的喜欢。 使用户哈希映射。 对于每个记录查找HashMap中的映射记录。 这将是肯定更多更快然后循环,找到一个记录。

所以很明显,加入应该是有利的。

注意:使用100记录的例子,可能产生相同的计划,但这个想法是分析它如何影响性能。



文章来源: Queries within queries: Is there a better way?