更新子查询中的数据

时间:2012-10-11 00:03:24

标签: java sql hibernate postgresql

我有两张桌子:

  • PERSONperson_idtotal
  • DATAdata_adata_bdata_cdata_person_id

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

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

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
  )

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

此外,任何改善此查询的方法都值得赞赏!

2 个答案:

答案 0 :(得分: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

答案 1 :(得分: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的FROM子句中使用此子查询。

  • 我使用IS DISTINCT FROM来确保覆盖NULL值,而只更改的行实际更新。
    如果定义了所有相关列NOT NULL,则可以改为使用=

-> sqlfiddle demo.