【问题标题】:Join only when relation data exists仅在存在关系数据时加入
【发布时间】:2021-04-04 04:54:30
【问题描述】:

这些是我的桌子。

CREATE TABLE IF NOT EXISTS categories (
  category_id serial primary key,
  category text not null,
  user_id int not null
);

CREATE TABLE IF NOT EXISTS activities (
  activity_id serial primary key,
  activity text not null,
  user_id int not null
);

CREATE TABLE IF NOT EXISTS categories_to_activities (
  category_id int not null REFERENCES categories (category_id) ON UPDATE CASCADE ON DELETE CASCADE,
  activity_id int not null REFERENCES activities (activity_id) ON UPDATE CASCADE ON DELETE CASCADE,
  CONSTRAINT category_activity_pkey PRIMARY KEY (category_id, activity_id)
);

这是我用来获取所有活动及其类别的查询。

SELECT a.*, ARRAY_AGG ( ROW_TO_JSON (c) ) categories
FROM activities a
JOIN categories_to_activities ca ON a.activity_id = ca.activity_id
JOIN categories c ON ca.category_id = c.category_id
WHERE a.user_id = ${userId}
GROUP BY a.activity_id

问题是,如果活动没有分配类别,则不会返回。

我无法将JOINCASE 结合起来,我想这是我需要的。本质上,我只想在categories_to_activities 中有记录时才JOIN

我该怎么做?

【问题讨论】:

    标签: sql postgresql join select


    【解决方案1】:

    您可以使用left join,并为没有类别的活动返回nulls:

    SELECT    a.*, 
              CASE WHEN ca.activity_id IS NOT NULL THEN ARRAY_AGG(ROW_TO_JSON(c)) 
                                                   ELSE ARRAY[]::JSON[] 
              END as categories
    FROM      activities a
    LEFT JOIN categories_to_activities ca ON a.activity_id = ca.activity_id
    LEFT JOIN categories c ON ca.category_id = c.category_id
    WHERE     a.user_id = ${userId}
    GROUP BY  a.activity_id
    

    【讨论】:

    • 我收到了Cannot convert undefined or null to object,我猜是因为ROW_TO_JSON 无法找到该类别。我现在在 SELECT 中需要那个 CASE,不是吗?
    • @VidličkaLujVitóón 这看起来不像是 PostgeSQL 错误。您是否在 Node.js 之外运行此查询?如果是这样,我会在那里检查它,而不是在查询本身中,但使用 case 也可以解决问题
    • 哦对,是后面JS抛出的错误。想用那个 CASE 更新你的答案吗?我想得到空数组而不是[null]。谢谢!
    • @VidličkaLujVitóón 实际上,使用 coalesce 甚至比 case 更干净 - 请参阅我编辑的答案
    • @VidličkaLujVitóón 好收获!我错过了array_agg 处理nulls 的方式。我已将其编辑到我的答案中,以便将来查找它的人更有用。
    【解决方案2】:

    感谢@Murenik,我最终得到了什么

    SELECT    a.*,
              CASE WHEN ca.activity_id IS NOT NULL
                THEN ARRAY_AGG ( ROW_TO_JSON (c) )
                ELSE ARRAY[]::JSON[]
              END as categories
    FROM      activities a
    LEFT JOIN categories_to_activities ca ON a.activity_id = ca.activity_id
    LEFT JOIN categories c ON ca.category_id = c.category_id
    WHERE     a.user_id = ${userId}
    GROUP BY  a.activity_id, ca.activity_id
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-26
      • 2013-04-24
      • 2022-01-09
      • 1970-01-01
      • 2015-01-11
      相关资源
      最近更新 更多