一个简单的实际问题:我有一个表const_a
,其中包含大量的行和列。
当我打电话给SELECT A, B, C FROM const_a WHERE restrictive_conditions
时,我会得到所有我想处理的行以及唯一需要的列。
行按列A
分组,值在列C
中,选项在列B
中。我的目标是从至少有一行的所有C
组中获取所有A
的值,其中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
的限制不是很严格,并且我不想在restrictive_conditions
中重复SELECT DISTINCT
,所以我将使用WITH
子句,例如:
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')
此查询在合理的时间内起作用,并返回期望值。
最后一个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 Developer客户端都不会给出任何此类指示,只是连接断开。有人有解决方案吗?
这是根据sqlplus命令使用Oracle数据库10g企业版10.2.0.3.0完成的。我已经输入了所有这些内容,因此错误并非来自简单的错字,但感谢您的任何纠正。
编辑:我必须指定,在/*+ MATERIALIZE */
子句中的SELECT
之后也添加了WITH
,它没有什么不同。
编辑2:没关系,我以为我找到了空子句。
编辑3:大家好,我找到了解决方案,或者我应该说我找到了问题。
我确实有多个“ C
”列,其中之一是CLOB列。我发现奇怪的是,MatBailie的代码在键入时能正常工作,但不是我的,所以我真的尝试通过一点一点地更改MatBailie的查询来构建自己的查询,而当我要求添加其他值列时,它停止工作并尝试添加一个或另一个表明我的CLOB(和我测试过的,与BLOB相同)列太多了。我将不得不使用其他查询。
由于MatBailie是正确的,所以我接受他的解决方案。也感谢APC的帮助,尽管我没有尝试。我觉得这种痕迹可能暗示了正确的解决方案。
答案 0 :(得分:2)
您的方法应按书面规定工作,请参见此测试:
但是,我认为您可以通过使用解析函数而不是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'
,它将返回1,否则,它将返回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
要获得更清晰的解释,请查找分析函数或窗口函数。