无法匹配 AWS Redshift 中视图的计算字段上的 WHERE 条件

问题描述 投票:0回答:1

当我在视图的 WHERE 条件中包含一列时,它与值不匹配。相反,当我在 where 条件下使用 TRIM(column) 时,它工作正常。数据不包含任何尾随空格,因为它是我创建的计算字段。该视图正在从其他视图获取数据。 以下是在您这边重现问题的步骤。

我创建了一个测试。

create table test(id int);
insert into test values(1),(2),(3),(4),(2),(3);

我在它上面创建了一个视图来忽略 id 4。

create or replace view test_view as select * from test where id <> 4;

我使用另一个视图在此视图上创建了一个计算字段。

create view test_view_1 as 
Select case id 
when 1 then 'Aman'::text 
when 2 then 'Boy'::character varying 
else 'Active' 
end as status from test_view;

现在让我们看看数据。

select * from test_view_1

输出: 状态(列名称)

Aman
Boy
Active
Boy
Active

当我使用 where 条件时,它没有给我任何输出。

select * from test_view_1 where status = 'Aman';

无输出

当我在状态上使用 TRIM 时,它会给出输出。

select * from test_view_1 where TRIM(status) = 'Aman';

输出: 状态 (列名称)

Aman

我很失落。我希望这个问题的逐步描述能够帮助您更好地理解并帮助我。由于一些限制,我需要使用多个视图的视图。我希望我能在这方面找到一些帮助。

注意:当我使用 Redshift 中默认的 COLLATE SENSITIVE 时,这不是问题。当我使用 COLLATE INSENSITIVE 处理数据库时出现了这个问题。

amazon-redshift
1个回答
0
投票

有趣的案例。 我相信您已经发现了新的排序不敏感功能(至少因为它作为数据库功能应用)的 Redshift 错误。 您应该将此提交给 AWS。

这里发生的事情是,整理不敏感正在与块元数据比较交叉。 您会看到 Redshift 将 WHERE 子句值与块元数据值进行比较,以查看需要读入哪些块。只有当 WHERE 子句中引用的列未被函数操作时,才会发生这种情况。 如果未读入某个块,则该块的任何结果都会显示在结果中。 我无法证明这一点,但它符合我进行的实验 - 见下文。 Redshift 正在获取所有 SQL,包括视图定义,并通过查询编译器运行它。 它寻找从 WHERE 子句“安全”向后工作的方法,以查明它是否可以将 WHERE 子句应用于表的块元数据。 由于您的 CASE 语句很简单,因此可以这样:“Aman”仅在 id 为 1 时才会出现,因此请检查元数据中的值是否为 1。当启用校对敏感时,这一切都可以正常工作。

当整理对数据库不敏感时,Redshift 会以某种方式混淆应用此推断的元数据检查。 我能够重现您的示例 - 见下文。

您的 TRIM() 案例有效,因为将函数应用于 WHERE 子句中的列会破坏 Redshift 进行元数据比较的能力。 我将此函数更改为 NVL(),查询再次有效。 这是这个娱乐活动:

-- create database foo COLLATE CASE_INSENSITIVE; -- switch to this new DB drop table if exists test cascade; create table test(id int); insert into test values(1),(2),(3),(4),(2),(3); create or replace view test_view as select * from test where id <> 4; create view test_view_1 as Select case id when 1 then 'Aman'::text when 2 then 'Boy'::character varying else 'Active' end as status from test_view; select * from test_view_1; select * from test_view_1 where nvl(status,'') = 'Aman';

使查询工作的其他函数示例:

select * from test_view_1 where status||'' = 'Aman'; select * from test_view_1 where translate(status,'x','y') = 'Aman';

毫不奇怪,这个函数没有使查询工作,因为更改字符串大小写对于这个数据库来说是无操作的:

select * from test_view_1 where lower(status) = 'Aman';

除了提交错误报告之外,您还可以像使用 TRIM() 或 WHERE 子句中应用的几乎任何其他函数一样解决此问题。  这意味着如果不进行调整,所有查询都可能遇到此危险,并且可能会导致持续出现问题,直到错误得到修复。  可能还有其他解决方法,但了解真正的原因会让您对任何解决方法充满信心。

现在这只是关于此问题背后机制的理论,但您一定要联系 AWS 支持。

© www.soinside.com 2019 - 2024. All rights reserved.