为什么调用两个 WITH 子句,一个调用另一个,不起作用?
Why do calling two WITH clauses, with one calling the other, not work?
简单的实际问题:我有一个 table、const_a
,其中包含大量的行和列。
当我调用 SELECT A, B, C FROM const_a WHERE restrictive_conditions
时,我获得了我希望处理的所有行和我需要的唯一列。
行按 A
列分组,值在 C
列中,选项在 B
列中。我的目标是从所有 A
组中获取所有 C
值,这些组至少有一行 B
具有特定值,比方说 'v'
.
第一个查询将是:
SELECT C FROM const_a
WHERE restrictive_conditions
AND A IN (SELECT DISTINCT A FROM const_a WHERE B LIKE 'v')
B LIKE 'v'
对 const_a
的限制不是很大,我不想在 SELECT DISTINCT
中重复 restrictive_conditions
,所以我将使用 [=26] =] 子句,像这样:
WITH tmp_a AS (SELECT A, B, C FROM const_a WHERE restrictive_conditions)
SELECT C FROM tmp_a
WHERE A IN (SELECT DISTINCT A FROM tmp_a WHERE B LIKE 'v')
此查询在合理的时间内有效,并且 returns 预期值。
最后一个SELECT DISTINCT
在查询的上下文中比较晦涩,所以为了便于理解,我添加了第二个WITH
:
WITH tmp_a AS (SELECT A, B, C, FROM const_a WHERE restrictive_conditions),
tmp_b AS (SELECT DISTINCT A FROM tmp_a WHERE B LIKE 'v')
SELECT C FROM tmp_a WHERE A IN (SELECT A FROM tmp_b) ;
我给 tmp_a
和 tmp_b
取了有意义的名字,这里它类似于 minimal_range
和 valid_groups
,收工了,但是当我尝试运行 这个查询我不断收到断开连接错误,根据我的搜索表明 Oracle 在后台自行崩溃,没有告诉我。
我已经尝试并测试了所有的别名方式,使用 INNER JOIN
而不是 WHERE ... IN ...
,但没有成功;当我有两个或多个 WITH
子句时,一个调用另一个,然后我将它们一起调用,它会崩溃。根据我构建它的方式,我也得到了空结果(尽管独立尝试不同的部分给出了预期的结果,就好像 WITH
子句在被另一个子句调用后自行清空)。这不是期望的结果。
在这种情况下,我可以使用不同的查询,但我想知道如何一起使用嵌套的 WITH
子句。其他人也可能从中受益。
有人可以解释为什么这不起作用吗?我希望这是一个简单的语法错误,但控制台和 Oracle SQL 开发人员客户端都没有给出任何此类指示,只是连接丢失。有人有解决办法吗?
根据 sqlplus 命令,这是使用 Oracle 数据库 10g 企业版 10.2.0.3.0 版完成的。我已经输入了所有内容,所以错误不是简单的打字错误,但感谢您的任何更正。
编辑:我必须说明,我还在我的 WITH
子句中的 SELECT
之后添加了 /*+ MATERIALIZE */
,它没有做任何不同的事情。
编辑 2:没关系,我以为我找到了空子句。
Edit 3 : 大家好,我找到了解决办法,或者说我找到了问题所在。
我确实有多个“C
”列,其中之一是 CLOB 列。我发现很奇怪,当我输入 MatBailie 的代码时它起作用了,但我的却不起作用,所以我真的试着通过一点一点地改变他的代码来重建我自己的查询,当我要求额外的值列时,它停止工作,并试图添加一个或另一个表明我的 CLOB(我测试过,与 BLOB 相同)列太多了。我将不得不使用不同的查询。
既然 MatBailie 是正确的,我就接受他的解决方案。也感谢 APC 的帮助,尽管我没有尝试过。我有一种感觉,跟踪会暗示正确的解决方案。
你的方法应该像写的那样有效,请看这个测试:
不过,我认为您可以通过使用解析函数而不是 IN()
...
来简化计算过程
WITH
restrict_and_check AS
(
SELECT
A, B, C,
MAX(CASE WHEN B = 'v' THEN 1 ELSE 0 END)
OVER (
PARTITION BY A
)
AS a_includes_b_that_equals_v
FROM
const_a
WHERE
restrictive_condition
)
SELECT
C
FROM
restrict_and_check
WHERE
a_includes_b_that_equals_v = 1
MAX() OVER ()
就像一个子查询,带有聚合函数。
在上面的示例中,它按列 A
对数据进行分区,并将具有相同值的所有行传递给函数。
本例中的函数是 MAX(CASE WHEN B = 'v' THEN 1 ELSE 0 END)
,如果任何传入行具有 B = 'v'
,它将 return 为 1,否则它将 return 0
.
有点像...
SELECT
*
FROM
a_data_set
INNER JOIN
(
SELECT
A,
MAX(CASE WHEN B = 'v' THEN 1 ELSE 0 END) AS a_includes_b_that_equals_v
FROM
a_data_set
GROUP BY
A
)
a_check
ON a_check.A = a_data_set.A
要获得更清晰的解释,请查看解析函数或窗口函数。
简单的实际问题:我有一个 table、const_a
,其中包含大量的行和列。
当我调用 SELECT A, B, C FROM const_a WHERE restrictive_conditions
时,我获得了我希望处理的所有行和我需要的唯一列。
行按 A
列分组,值在 C
列中,选项在 B
列中。我的目标是从所有 A
组中获取所有 C
值,这些组至少有一行 B
具有特定值,比方说 'v'
.
第一个查询将是:
SELECT C FROM const_a
WHERE restrictive_conditions
AND A IN (SELECT DISTINCT A FROM const_a WHERE B LIKE 'v')
B LIKE 'v'
对 const_a
的限制不是很大,我不想在 SELECT DISTINCT
中重复 restrictive_conditions
,所以我将使用 [=26] =] 子句,像这样:
WITH tmp_a AS (SELECT A, B, C FROM const_a WHERE restrictive_conditions)
SELECT C FROM tmp_a
WHERE A IN (SELECT DISTINCT A FROM tmp_a WHERE B LIKE 'v')
此查询在合理的时间内有效,并且 returns 预期值。
最后一个SELECT DISTINCT
在查询的上下文中比较晦涩,所以为了便于理解,我添加了第二个WITH
:
WITH tmp_a AS (SELECT A, B, C, FROM const_a WHERE restrictive_conditions),
tmp_b AS (SELECT DISTINCT A FROM tmp_a WHERE B LIKE 'v')
SELECT C FROM tmp_a WHERE A IN (SELECT A FROM tmp_b) ;
我给 tmp_a
和 tmp_b
取了有意义的名字,这里它类似于 minimal_range
和 valid_groups
,收工了,但是当我尝试运行 这个查询我不断收到断开连接错误,根据我的搜索表明 Oracle 在后台自行崩溃,没有告诉我。
我已经尝试并测试了所有的别名方式,使用 INNER JOIN
而不是 WHERE ... IN ...
,但没有成功;当我有两个或多个 WITH
子句时,一个调用另一个,然后我将它们一起调用,它会崩溃。根据我构建它的方式,我也得到了空结果(尽管独立尝试不同的部分给出了预期的结果,就好像 WITH
子句在被另一个子句调用后自行清空)。这不是期望的结果。
在这种情况下,我可以使用不同的查询,但我想知道如何一起使用嵌套的 WITH
子句。其他人也可能从中受益。
有人可以解释为什么这不起作用吗?我希望这是一个简单的语法错误,但控制台和 Oracle SQL 开发人员客户端都没有给出任何此类指示,只是连接丢失。有人有解决办法吗?
根据 sqlplus 命令,这是使用 Oracle 数据库 10g 企业版 10.2.0.3.0 版完成的。我已经输入了所有内容,所以错误不是简单的打字错误,但感谢您的任何更正。
编辑:我必须说明,我还在我的 WITH
子句中的 SELECT
之后添加了 /*+ MATERIALIZE */
,它没有做任何不同的事情。
编辑 2:没关系,我以为我找到了空子句。
Edit 3 : 大家好,我找到了解决办法,或者说我找到了问题所在。
我确实有多个“C
”列,其中之一是 CLOB 列。我发现很奇怪,当我输入 MatBailie 的代码时它起作用了,但我的却不起作用,所以我真的试着通过一点一点地改变他的代码来重建我自己的查询,当我要求额外的值列时,它停止工作,并试图添加一个或另一个表明我的 CLOB(我测试过,与 BLOB 相同)列太多了。我将不得不使用不同的查询。
既然 MatBailie 是正确的,我就接受他的解决方案。也感谢 APC 的帮助,尽管我没有尝试过。我有一种感觉,跟踪会暗示正确的解决方案。
你的方法应该像写的那样有效,请看这个测试:
不过,我认为您可以通过使用解析函数而不是 IN()
...
WITH
restrict_and_check AS
(
SELECT
A, B, C,
MAX(CASE WHEN B = 'v' THEN 1 ELSE 0 END)
OVER (
PARTITION BY A
)
AS a_includes_b_that_equals_v
FROM
const_a
WHERE
restrictive_condition
)
SELECT
C
FROM
restrict_and_check
WHERE
a_includes_b_that_equals_v = 1
MAX() OVER ()
就像一个子查询,带有聚合函数。
在上面的示例中,它按列 A
对数据进行分区,并将具有相同值的所有行传递给函数。
本例中的函数是 MAX(CASE WHEN B = 'v' THEN 1 ELSE 0 END)
,如果任何传入行具有 B = 'v'
,它将 return 为 1,否则它将 return 0
.
有点像...
SELECT
*
FROM
a_data_set
INNER JOIN
(
SELECT
A,
MAX(CASE WHEN B = 'v' THEN 1 ELSE 0 END) AS a_includes_b_that_equals_v
FROM
a_data_set
GROUP BY
A
)
a_check
ON a_check.A = a_data_set.A
要获得更清晰的解释,请查看解析函数或窗口函数。