2

我有两张桌子:

  • PERSON与列person_idtotal
  • DATAdata_a, data_b, data_c, 和data_person_id

每个“人”可以有零个或多个条目DATA- 您的标准一对多关系。PERSON有一total列是 中的值的总和DATA。目前在正确但错误的地方total与实际条目之间存在一些差异。DATADATAtotal

这是我用来查找差异的查询:

SELECT
  person_id
FROM PERSON JOIN (
  SELECT
    data_person_id,
    SUM( data_a + data_b + data_c ) as data_total
  FROM
    DATA
  GROUP BY
    data_person_id
  ) x ON data_person_id = person_id
WHERE
  person_total != data_total

我计划通过 Hibernate 作为后端将是 Postgres 9.x 的查询来执行此操作。

我试图理解/修复的错误查询是:

UPDATE
  ONLY PERSON
SET
  total = data_info.calc_total
FROM (
  SELECT
    SUM( data_a + data_b + data_c ) as calc_total
  FROM
    DATA
  WHERE
    DATA.data_person_id = person_id
  GROUP BY
    DATA.data_person_id
) as data_info
WHERE
  PERSON.person_id IN (
    SELECT
      data_person_id
    FROM PERSON JOIN (
      SELECT
        data_person_id,
        SUM( data_a + data_b + data_c ) as data_total
      FROM
        DATA
      GROUP BY
        data_person_id
      ) x ON person_id = data_person_id
    WHERE
      total != data_total
  )

现在,它不会运行,因为WHERE DATA.data_person_id = person_id. 但如果我把它拿出来,就会使用错误的值。

以下似乎有效,但我对为什么感到困惑:

UPDATE
  ONLY PERSON
SET
  total = data_info.calc_total
FROM 
  PERSON P JOIN (
    SELECT
      data_person_id,
      SUM( data_a + data_b + data_c ) as calc_total
    FROM
      DATA
    WHERE
      DATA.data_person_id = person_id
    GROUP BY
      DATA.data_person_id
  ) as data_info ON P.person_id = data_person_id
WHERE
  PERSON.person_id IN (
    SELECT
      data_person_id
    FROM PERSON JOIN (
      SELECT
        data_person_id,
        SUM( data_a + data_b + data_c ) as data_total
      FROM
        DATA
      GROUP BY
        data_person_id
      ) x ON person_id = data_person_id
    WHERE
      total != data_total
  )

我相信我的问题在于我对文档的误解(我猜测关于自加入的部分)。

此外,感谢任何改进此查询的方法!

4

2 回答 2

2

似乎您的查询很复杂。任务应该很简单:

UPDATE person p
SET    total = d.calc_total
FROM (
  SELECT data_person_id, sum(data_a + data_b + data_c) as calc_total
  FROM   data
  GROUP  BY 1
) d
WHERE  p.person_id = d.data_person_id
AND    p.total IS DISTINCT FROM d.calc_total;
  • calc_total表中的第一个聚合data,按 分组data_person_id

  • 然后在UPDATE.

  • IS DISTINCT FROM用来确保 NULL 值被覆盖,而实际上只有会更改的行被更新。
    如果定义了所有涉及的列NOT NULL,则可以=改用。

-> sqlfiddle 演示。

于 2012-10-11T00:44:47.757 回答
2

这是普通的语法UPDATE...FROM。因此,使用 WHERE 之外的最后一个查询

UPDATE
  ONLY PERSON
SET
  total = data_info.calc_total
FROM 
  PERSON P JOIN (
    SELECT
      data_person_id,
      SUM( data_a + data_b + data_c ) as calc_total
    FROM
      DATA
    WHERE
      DATA.data_person_id = person_id
    GROUP BY
      DATA.data_person_id
  ) as data_info ON P.person_id = data_person_id
于 2012-10-11T00:24:31.240 回答