我怎样才能将这两个相关的查询结合起来?

Posted

技术标签:

【中文标题】我怎样才能将这两个相关的查询结合起来?【英文标题】:How can I unite these two related queries? 【发布时间】:2021-03-20 07:51:52 【问题描述】:

我有这个查询来检查一个人是否是客户或曾经是:

SELECT DISTINCT ON (person_id) person_id, person.name, 
      (CASE WHEN status = 'inactive' then 'Ex-Customer'
            WHEN status = 'active' then 'Customer'
        END) AS account_status
FROM person_subscription
INNER JOIN person ON person_subscription.person_id = person.id
ORDER BY person_id, status ASC

我还有其他查询来获取位置:

SELECT   person_id, string_agg(name, ';' ORDER BY person_id) 
FROM    person_location WHERE person_id IN 
(SELECT person_id FROM person_subscription WHERE status IS NOT NULL)
GROUP BY person_id;

如何将它们合并并在第一个查询中将人员位置显示为单行?

【问题讨论】:

第一个查询缺少order by 子句 - 没有它,当每个人有多个匹配项时,将选择哪一行是未定义的。 @GMB 我没有正确复制,现在已修复。 【参考方案1】:

你会加入:

SELECT DISTINCT ON (ps.person_id) ps.person_id, ps.person.name, 
      (CASE WHEN ps.status = 'inactive' then 'Ex-Customer'
            WHEN ps.status = 'active' then 'Customer'
        END) AS account_status
FROM person_subscription ps INNER JOIN
     person p
     ON ps.person_id = p.id LEFT JOIN
     (SELECT pl.person_id, STRING_AGG(pl.name, ';') as names
      FROM person_location pl
      GROUP BY pl.person_id
     ) pl
     ON pl.person_id = p.id
ORDER BY ps.person_id, p.status ASC;

我不确定WHERE 子句对于获取位置的意义,但您也可以将其包含在子查询中。

【讨论】:

我收到missing FROM-clause entry for table "person" @MaddWorld 。 . . person 在您的第一个查询中。我刚刚添加了表别名。【参考方案2】:

如果我正确地遵循了这一点,您可以使用横向连接:

select p.id as person_id, p.name, pl.*, ps.*
from person p
cross join lateral (
    select string_agg(pl.name, ';' order by pl.name) as as person_locations
    from person_location pl
    where pl.person_id = p.id
) pl
cross join lateral (
    select 
        case status 
            when 'inactive' then 'ex-customer'
            when 'active' then 'customer'
        end as account_status
    from person_subscription ps
    where ps.person_id = p.id
    order by ps.??
    limit 1
) ps

正如已经评论的那样,您最初的第一个查询缺少order by 子句,这使得在有多个匹配项时将选择哪个订阅状态未定义。这在第二个子查询中转换为 order by ps.??,您需要将其替换为相关的列名。

另一个缺陷,即在您问题的第二个查询中,string_agg()order by 子句不是确定性的(组中的所有行都具有相同的 person_id)。我改为按位置名称排序,如果您愿意,可以将其更改为其他列。

【讨论】:

以上是关于我怎样才能将这两个相关的查询结合起来?的主要内容,如果未能解决你的问题,请参考以下文章

我怎样才能结合这两个代码? (python图像查看器+鼠标拖动图像ROI裁剪)

如何将这两条 SQL 语句合并为一条?

Django:结合来自两个过滤器查询的两个计数注释

PyYaml 结合两个 yaml 文件

如何将一个字段中的日期与另一字段中的时间结合起来 - MS SQL Server

让 tableView 从 NSUserDefaults 中删除滑动删除项目 - 如何将这两个功能结合在一起?