【问题标题】:PostgreSQL pass value into INNER JOINPostgreSQL 将值传递给 INNER JOIN
【发布时间】:2020-11-13 06:43:49
【问题描述】:

PostgreSQL 11

如何将o.create_date 值传递给INNER JOIN?在o.create_date之前我需要Max ID

SELECT o.id,
       o.create_date               date,
       sum(oi.quantity)            qty,
       sum(oi.quantity * sp.price) total
FROM ax_order o
         LEFT JOIN ax_order_invenotry oi on o.id = oi.order_id
         LEFT JOIN ax_inventory i on i.id = oi.inventory_id
         LEFT JOIN ax_suppliers s on s.id = o.supplier_id
         INNER JOIN ax_supplier_price sp ON (sp.inventory_id = oi.inventory_id and sp.supplier_id = o.supplier_id)
         INNER JOIN
     (
         SELECT inventory_id,
                max(id) id
         FROM ax_supplier_price
         WHERE create_date <= o.create_date
         GROUP BY inventory_id
     ) lsp ON (sp.id = lsp.id)
WHERE o.store_id = 13
  AND o.supplier_id = 35
GROUP BY o.id, o.create_date
ORDER BY o.id

【问题讨论】:

  • 请详细说明您的表结构、示例数据和所需输出的问题

标签: postgresql subquery inner-join postgresql-11


【解决方案1】:

您可以使用 LATERAL join mechanism 使其工作:

WITH ax_order AS (
    SELECT *
    FROM (VALUES (1, '2000-1-1'::date, 1, 1)) as x(id, create_date, store_id, supplier_id)
), ax_order_inventory AS (
    SELECT *
    FROM (VALUES (1, 2, 4)) as x(order_id, inventory_id, quantity)
), ax_supplier_price AS (
    SELECT *
    FROM (VALUES (1, 2, 1, 10, '1999-12-31'::date)) as x(id, inventory_id, supplier_id, price, create_date)
)
SELECT o.id,
       o.create_date               date,
       sum(oi.quantity)            qty,
       sum(oi.quantity * sp.price) total
FROM ax_order o
         LEFT JOIN ax_order_inventory oi on o.id = oi.order_id
         INNER JOIN ax_supplier_price sp ON (sp.inventory_id = oi.inventory_id and sp.supplier_id = o.supplier_id)
         INNER JOIN LATERAL
     (
         SELECT inventory_id,
                max(lsp.id) id
         FROM ax_supplier_price lsp
         WHERE sp.create_date <= o.create_date
         GROUP BY inventory_id
     ) lsp ON sp.id = lsp.id
GROUP BY o.id, o.create_date
ORDER BY o.id

我删除了一些并非绝对必要的 JOIN,并尽可能地模拟了您的数据。但是请注意,您也可以使用 WHERE 子句来查找它 - 这应该更有效:

WITH ax_order AS (
    SELECT *
    FROM (VALUES (1, '2000-1-1'::date, 1, 1)) as x(id, create_date, store_id, supplier_id)
),
     ax_order_inventory AS (
         SELECT *
         FROM (VALUES (1, 2, 4)) as x(order_id, inventory_id, quantity)
     ),
     ax_supplier_price AS (
         SELECT *
         FROM (VALUES (1, 2, 1, 10, '1999-12-31'::date)) as x(id, inventory_id, supplier_id, price, create_date)
     )
SELECT o.id,
       o.create_date               date,
       sum(oi.quantity)            qty,
       sum(oi.quantity * sp.price) total
FROM ax_order o
         LEFT JOIN ax_order_inventory oi on o.id = oi.order_id
         INNER JOIN ax_supplier_price sp
                    ON (sp.inventory_id = oi.inventory_id and sp.supplier_id = o.supplier_id)
WHERE sp.id =
      (
          -- NOTE: no GROUP BY necessary!
          SELECT max(lsp.id) id
          FROM ax_supplier_price lsp
          WHERE sp.create_date <= o.create_date
            AND lsp.inventory_id = sp.inventory_id
      )
GROUP BY o.id, o.create_date
ORDER BY o.id

【讨论】:

  • 它可以工作,但 LATERAL 类型需要 18 000 毫秒。在第二个示例中,最后一个 WHERE (SELECT...) 没有横向?
  • 是的,那里不需要 LATERAL。我无法为您测试性能,但我相信它应该更快
  • WHERE sp.id = ( -- 注意:不需要 GROUP BY!SELECT max(lsp.id) id FROM ax_supplier_price lsp !!! WHERE lsp.create_date
  • 我不明白你的意思
  • 不错!乐于助人
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-15
  • 2013-02-08
相关资源
最近更新 更多