将常规选择语句转换为相关子查询?

时间:2017-03-05 01:34:35

标签: sql database oracle select correlated-subquery

我有以下SQL查询:

 SELECT name, transaction_id, MIN(transaction_date)
 FROM clients
 JOIN transactions ON clients.client_id = transactions.client_id
 GROUP BY name, transaction_id;

我希望使用以下结构变成相关子查询

 SELECT a, b, MIN(c)
 FROM t1
 JOIN t2 ON t1.d = t2.d
 WHERE c IN
      (SELECT * 
      FROM t2
      HAVING....)

其中a, b, c是列名,t1, t2是表。

但我在这个过程中遇到了困难。

作为参考,原始问题是要求返回每个客户最早的transaction_date及其对应的transaction_id。

因此,如果transactions表具有以下内容:

   transaction_id    client_id      transaction_date
         1               1              02-02-17
         2               1              02-01-17
         3               2              02-03-17
         4               2              02-04-17

相关子查询将返回:

    name       transaction_id       transaction_date
    John            2                   02-01-17
    Mary            3                   02-03-17

2 个答案:

答案 0 :(得分:1)

您的查询不符合您的想法。一个正确的查询是:

SELECT c.name, t.transaction_id, t.transaction_date
FROM clients c JOIN
     transactions t
     ON c.client_id = t.client_id
WHERE t.transaction_date = (SELECT MIN(t2.transaction_date)
                            FROM transactions t2
                            WHERE t2.client_id = t.client_id
                           );

更典型的查询是:

SELECT name, transaction_id, transaction_date
FROM (SELECT c.name, t.transaction_id, t.transaction_date,
             ROW_NUMBER() OVER (PARTITION BY c.client_id ORDER BY t.transaction_date) as seqnum
      FROM clients c JOIN
           transactions t
           ON c.client_id = t.client_id 
     ) ct
WHERE seqnum = 1;

答案 1 :(得分:0)

在oracle 12c中有CROSS APPLYOUTER APPLY条款:
(在this link中查找cross_outer_apply_clause):

  

<强> cross_outer_apply_clause

     

此子句允许您执行ANSI CROSS JOIN或的变体   ANSI LEFT OUTER JOIN 左侧关联支持。你可以指定   APPLY右侧的table_reference或collection_expression   关键词。 table_reference可以是表,内联视图或TABLE   集合表达。 collection_expression可以是子查询,a   列,函数或集合构造函数。无论如何   form,它必须返回一个集合值 - 即类型为的值   嵌套表或varray。 table_reference或collection_expression   可以引用FROM子句中定义的表的列到左侧   APPLY关键字。 这称为左相关

这两个子句有一个(左)相关支持 - 这只是意味着可以使用相关的子查询。

您的查询可能如下所示:

select c.*, x.*
from clients c
cross apply (
   select transaction_id, transaction_date
   from transactions t
   where t.client_id = c.client_id
   order by transaction_date desc
   fetch first row only
) x

或使用outer apply

select c.*, x.*
from clients c
outer apply (
   select transaction_id, transaction_date
   from transactions t
   where t.client_id = c.client_id
   order by transaction_date desc
   fetch first row only
) x

后一个查询类似于LEFT JOIN - 它为所有客户端提供包括没有任何事务的客户端,而前一个客户端就像INNER JOIN并且只列出至少有1个事务的客户端。 />
两个查询都使用右侧的相关子查询,这些子查询使用引用左侧表格的where t.client_id = c.client_id条件。