只允许作为***合取的 SubQuery 表达式

Posted

技术标签:

【中文标题】只允许作为***合取的 SubQuery 表达式【英文标题】:Only SubQuery expressions that are top level conjuncts are allowed 【发布时间】:2020-06-24 15:57:43 【问题描述】:

我想更改现有查询并收到以下错误:

不支持的子查询表达式“已删除”:仅允许作为***合取的子查询表达式

现有查询是:

SELECT DISTINCT
    *
FROM
    geoposition_import AS geo
-- do not take into account data for deleted users
WHERE 
    EXISTS (
        SELECT 1 
        FROM geoposition_import_users AS u 
        WHERE u.id = geo.userId 
            AND NOT u.deleted 
    );

在我们更改之后,geoposition_import 中的 userId 可以为空,因为现在机器也可以创建地理位置。所以我将查询更改为

SELECT DISTINCT
    *
FROM
    geoposition_import AS geo
-- do not take into account data for deleted users
WHERE 
    geo.userId IS NULL -- data from non users (e.g. machines) is still fine
    OR
    EXISTS (
        SELECT 1 
        FROM geoposition_import_users AS u 
        WHERE u.id = geo.userId 
            AND NOT u.deleted 
    );

得到了上面提到的错误。

我用谷歌搜索并找到了限制:https://docs.cloudera.com/HDPDocuments/HDP3/HDP-3.1.5/using-hiveql/content/hive_hive_subquery_limitations.html

所以我的猜测是:OR 是问题所在。

现在我的问题:

    为什么错误消息表明“删除”是问题所在? 如何重写查询以使其正常工作?

我想到的唯一解决方案是:将条件拆分为单独的视图,然后执行UNION ALL

喜欢:

CREATE VIEW IF NOT EXISTS geoposition_import_from_non_users AS
SELECT DISTINCT
    *
FROM
    geoposition_import AS geo
WHERE 
    geo.userId IS NULL;

CREATE VIEW IF NOT EXISTS geoposition_import_from_users AS
SELECT DISTINCT
    *
FROM
    geoposition_import AS geo
-- do not take into account data for deleted users
WHERE 
    EXISTS (
        SELECT 1 
        FROM geoposition_import_users AS u 
        WHERE u.id = geo.userId 
            AND NOT u.deleted 
    );

-- staged data with possible duplicates removed
CREATE VIEW IF NOT EXISTS geoposition_import_distinct AS
SELECT * FROM geoposition_import_from_non_users
UNION ALL
SELECT * FROM geoposition_import_from_users;

有没有cmets?

【问题讨论】:

u.deleted 列类型是什么?或者此列中的数据是什么 @leftjoin 布尔值。正如我所说:多年来没有空检查的第一个版本运行良好:) 【参考方案1】:

尝试 LEFT JOIN 而不是 EXISTS:

 SELECT DISTINCT
    geo.*
FROM geoposition_import geo
     LEFT JOIN geoposition_import_users u ON u.id=geo.userId AND NOT u.deleted     
WHERE 
    geo.userId IS NULL -- data from non users (e.g. machines) is still fine
    OR u.id IS NOT NULL;

【讨论】:

好的,我会的。但我需要SELECT DISTINCT geo.* 而不是SELECT DISTINCT * 对吗?

以上是关于只允许作为***合取的 SubQuery 表达式的主要内容,如果未能解决你的问题,请参考以下文章

枚举真值表生成主合取范式 主析取范式

转换为 XOR 合取形式

LEFT JOIN 和 SUBQUERY 与空列 / null 作为结果

以合取范式书写条件

HIVE SubQuery 表达式同时引用 Parent 和 SubQuery 表达式

如何只允许一个表的一行?