【问题标题】:PostgreSQL Query with aggregates and RIGHT JOIN not filtering具有聚合和 RIGHT JOIN 的 PostgreSQL 查询未过滤
【发布时间】:2016-03-24 13:03:11
【问题描述】:

我在一对多地图上有两个表,库存和批次,在批次表上,我有一个名为已删除的布尔字段,所以我并没有真正删除行,而是将标志更改为被忽略且不计入查询,我正在尝试在一个查询中组合一个视图,但是如果我添加已删除的字段,则查询的 RIGHT JOIN 的行为类似于 INNER JOIN,我希望下面示例中的 ALL FROM 库存工作正常但不排除表 jap.lots 上的任何已删除记录。

    CREATE VIEW view_inventory_lots AS 
SELECT count(lots.*) AS lots,
sum(lots.qty_available) AS available,
sum(lots.qty_received) AS received,
sum(lots.qty_on_hand) AS onhand,
sum(lots.qty_allocated) AS allocated,
inventories.* 
FROM jap.lots RIGHT JOIN jap.inventories
 ON jap.lots.inventory_id = jap.inventories.inventory_id
  GROUP BY inventories.inventory_id;

如果我尝试修改此视图以添加 lot.deleted 字段以使用以下查询进行过滤:

SELECT count(lots.*) AS lots,
sum(lots.qty_available) AS available,
sum(lots.qty_received) AS received,
sum(lots.qty_on_hand) AS onhand,
sum(lots.qty_allocated) AS allocated,
lots.deleted,
inventories.* 
FROM jap.lots RIGHT JOIN jap.inventories
 ON jap.lots.inventory_id = jap.inventories.inventory_id
 WHERE lots.deleted = false
  GROUP BY inventories.inventory_id, lots.deleted;

结果只有在lots表上有记录的库存行,所以RIGHT JOIN的目的被忽略了,表现为INNER JOIN

有什么想法吗? 提前致谢

【问题讨论】:

  • 常见的约定是用行标识的单数而不是复数来命名表。这样,批次 => 批次和库存 => 库存
  • Hogan - 关于表名,您是对的,但这是我这边使用 Mongodb 完成的失败项目,最初是 mongo 以这种方式命名的,因此我保留了这个名称

标签: sql postgresql outer-join


【解决方案1】:

where 子句中使用“外部”表中的列将外部联接变为内部联接。将该表上的条件移动到join 条件中:

FROM jap.lots 
  RIGHT JOIN jap.inventories 
     ON jap.lots.inventory_id = ap.inventories.inventory_id
    AND lots.deleted = false
GROUP BY ...

【讨论】:

    【解决方案2】:

    我发现left joins 更容易理解——将所有行保留在 first 表中,并在其余行中匹配行。您的问题是 where 子句中的条件撤消了外连接。

    我会这样写:

    SELECT count(l.*) AS lots,
           sum(l.qty_available) AS available,
           sum(l.qty_received) AS received,
           sum(l.qty_on_hand) AS onhand,
           sum(l.qty_allocated) AS allocated,
           l.deleted,
           i.* 
    FROM jap.inventories i LEFT JOIN
         jap.lots l LEFT JOIN 
         ON l.inventory_id = i.inventory_id AND
            l.deleted = false
    GROUP BY i.inventory_id, l.deleted;
    

    还要注意表别名和限定列名的使用。这些使查询更易于编写和阅读。此外,它们使其更加一致:您对表名的使用在整个查询中不一致。

    【讨论】:

      猜你喜欢
      • 2018-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-05
      • 1970-01-01
      • 2016-05-02
      • 2017-05-24
      相关资源
      最近更新 更多