我正在玩PSQL的lateral
联接,特别是要对按/限制的组执行联接。
当我查找单个记录时,该查询工作得很好,但是当我们查询多个记录时,性能会很快下降。考虑到我们有多个子查询运行单独的聚集,过滤器聚合,排序,这是有道理的。问题是,我们应该看哪种PSQL策略,或者我们如何重构以下查询以使其大规模执行?
我们有三个主表,两个主表之间有一个连接表:
|经理| >-|商店| >-| Store_Products | -
我们具有给定商店记录的所有历史经理,并且我们具有商店产品的完整目录(产品可能由多个商店携带)。
目标:给出了商店ID,查询最新经理和最新销售的产品。
这是从商店到经理再到产品的内部连接。经理和产品必须按日期降序排序,并且限制为1(至少我认为这是获取最新日期的方式)。
SELECT
store.id as store_id,
manager.id as manager_id,
*
FROM
Stores as store,
LATERAL (
SELECT
*
FROM
Products as product
INNER JOIN Stores_Products store_product on store_product.product_id = product.id
WHERE
store_product.store_id = store.id
ORDER BY
store.date desc
LIMIT 1
) p,
LATERAL (
SELECT
*
FROM
Managers as manager
WHERE
manager.store_id = store.id
ORDER BY
manager.date desc
LIMIT 1
) m
WHERE store.name = 'ABC retail'
当您查询单个商店时,这非常理想。但是,如果您尝试批量查询(例如WHERE store.name in [...]
),查询将变得非常慢,并且内存消耗也会非常快。
是否有更好的方法来查询可扩展的数据?
谢谢!
注意:商店/产品给出的示例只是一个传达问题的设备。实际的架构有所不同-因此,我请不要过多考虑这是否是标准化架构的最佳方法!谢谢🙏!
也许窗口功能将运行得更快。在下面的代码中,产品订购属性保留为...
,因为在您的代码段中,它们似乎是按store.date订购的,这看起来是错误的(这是商店的属性,而不是产品的属性,而不是商品的属性。商店)。
SELECT * FROM
-- Let's rank managers within each store, giving rank=1 to the most recent
(
SELECT id,
store_id,
RANK() OVER (PARTITION BY store_id ORDER BY date DESC) AS mgr_rank
FROM Manager
) AS MgrRank
JOIN
-- Let's rank products within each store, giving rank=1 to the most recent
(
SELECT store_id,
Products.*
RANK() OVER (PARTITION BY store_id ORDER BY .... DESC) AS product_rank
FROM Stores_Products JOIN Products ON product_id = Products.id
) AS ProductRank
USING(store_id)
-- Now let's join stores themselves
JOIN Stores ON store_id = Stores.id
-- Select most recent manager and product
WHERE mgr_rank=1 AND product_rank=1 AND Stores.name='ABC retail'
请注意,没有经理或产品,此特定查询将不会输出商店。您还需要使用外部联接来包括它们。