Sql通过连接选择改进?

时间:2011-03-08 23:48:11

标签: sql postgresql

我如何改进以下查询,因为我认为我遗漏了一些东西而且可以做得更好:( 我有A表和A到B的一对多 我想要一些来自A的信息和来自B的一行链接到具有最高序号的A。 我想出了这个:

SELECT A.*, 
 (
  SELECT B.value
  FROM   B 
  WHERE A.idB = B.id
  ORDER BY B.seqNr DESC LIMIT 1
 )
FROM A

性能对我来说很重要,这是我最好的选择吗?

2 个答案:

答案 0 :(得分:1)

这可能是你最好的选择,特别是如果你只访问A和B中的少量行。

如果您打算覆盖所有行,您可以尝试使用窗口聚合解决问题,将行号分配给B中的行:

SELECT * FROM (
  SELECT A.*, B.*, ROW_NUMBER() OVER(PARTITION BY B.id ORDER BY B.seqNr DESC) AS seqidx
  FROM A JOIN B ON A.idB = B.id
) WHERE seqidx = 1

这将使用大量的临时空间...考虑只是将A和B主键从聚合中取出并稍后再加入它们(从您的查询中不清楚您的pkey列是什么,因为B. id显然不是)

答案 1 :(得分:0)

虽然更大,但这可能会更好。

SELECT
    A.*,
    B3.value
FROM
    (
        SELECT  B.id, MAX(B.seqNr) MaxSeqNr
        FROM    B
        GROUP BY    B.id
    ) B2
            INNER JOIN
    B B3
            ON
        B2.id = B3.id AND B2.MaxSeqNr = B3.seqNr
            INNER JOIN
    A
            ON
        A.id = B3.id

也可能会表现更差。需要一些真实的数据来测试和查看。 : - )

同时在B.id, B.seqNr DESC上创建复合索引可以提高原始和此备用查询的效果。

如果您可以阻止组织中的任何理论纯粹主义者,则可以通过添加LatestPaymentForA字段并使用触发器使此字段保持同步来显着提高性能。每当将新记录插入B时,更新现有记录B,其中LastPaymentFromA为真且具有相同id,然后将LastPaymentFromA的新记录插入真。

然后你可以像这样快速地做点什么:

SELECT
    A.*,
    B.value
FROM
    A
            INNER JOIN
    B
            On
        A.id = B.id
WHERE
    B.LastPaymentFromA = 1