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

Turning Regular Select Statements Into 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 是 tables。

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

供参考,原来的问题是问return每个客户中最早的transaction_date及其对应的transaction_id。

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

   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

相关子查询将 return:

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

您的查询与您认为的不符。正确的查询是:

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;

在 oracle 12c 中有 CROSS APPLYOUTER APPLY 子句:
(在 this link 中寻找 cross_outer_apply_clause):

cross_outer_apply_clause

This clause allows you to perform a variation of an ANSI CROSS JOIN or an ANSI LEFT OUTER JOIN with left correlation support. You can specify a table_reference or collection_expression to the right of the APPLY keyword. The table_reference can be a table, inline view, or TABLE collection expression. The collection_expression can be a subquery, a column, a function, or a collection constructor. Regardless of its form, it must return a collection value—that is, a value whose type is nested table or varray. The table_reference or collection_expression can reference columns of tables defined in the FROM clause to the left of the APPLY keyword. This is called left correlation.

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

您的查询可能如下所示:

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 条件,在左侧引用 table。