将常规 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 APPLY
和 OUTER 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。
我有以下 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 APPLY
和 OUTER 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。