3

我正在尝试更新如下所示的数据库的表 B:

Table A:
id, amount, date, b_id
1,200,6/31/2012,1
2,300,6/31/2012,1
3,400,6/29/2012,2
4,200,6/31/2012,1
5,200,6/31/2012,2
6,200,6/31/2012,1
7,200,6/31/2012,2
8,200,6/31/2012,2

Table B:
id, b_amount, b_date
1,0,0
2,0,0
3,0,0

现在通过这个查询,我可以在一次选择中获得我需要的所有数据:

SELECT A.*,B.* FROM A LEFT JOIN B ON B.id=A.b_id WHERE A.b_id>0 GROUP BY B.id

id, amount, date, b_id, id, b_amount, b_date
1,200,6/31/2012,1,1,0,0
3,400,6/29/2012,1,1,0,0

现在,我只想将选定的列金额复制到 b_amount 并将日期复制到 b_date

b_amount=amount, b_date=date

导致

id, amount, date, b_id, id, b_amount, b_date
1,200,6/31/2012,1,1,200,6/31/2012
3,400,6/29/2012,1,1,400,6/29/2012

我试过 COALESCE() 没有成功。有经验的人对此有解决方案吗?

解决方案:

感谢下面的答案,我设法想出了这个。这可能不是最有效的方法,但对于一次性更新来说没问题。这将为您插入每个组的第一个相应条目。

REPLACE INTO A SELECT id, amount, date FROM 
(SELECT  A.id, A.amount, B.id as Bid FROM A INNER JOIN B ON (B.id=A.B_id)
ORDER BY A.id DESC) 
GROUP BY Bid;
4

2 回答 2

1

因此,您正在寻找的似乎是 UPDATE 查询中的 JOIN 。在 mySQL 你会使用

UPDATE B INNER JOIN A ON B.id=A.b_id SET B.amount=A.amount, B.date=A.date;

但这不受 sqlite 的支持,因为这个可能相关的问题指出了这一点。但是,有一个使用 REPLACE 的解决方法:

REPLACE INTO B 
SELECT B.id, A.amount, A.date FROM A 
LEFT JOIN B ON B.id=A.b_id 
WHERE A.b_id>0 GROUP BY B.id;

查询将简单地为所有应保持其状态的列填写表 B 的值,并为复制的值填写表 A 的值。确保 SELECT 语句中的列顺序符合表 B 的列顺序,并且所有列都被提及,否则您将丢失这些字段的数据。这对于表 B 的未来更改可能很危险。因此请记住在更改表 B 时更改此查询的列顺序/存在。

有点跑题了,因为您没有要求:A.b_id显然是 B.id 的外键。您似乎正在使用0外键的值来表示 B 中没有相应的条目。(从您的 SELECT 中推断出来WHERE A.b_id>0。)您应该考虑使用该null值。当您使用INNER JOINthen 而不是时,LEFT JOIN您可以完全删除 WHERE 子句。然后星展银行将整理所有不满意的关系。

于 2012-06-05T18:21:49.000 回答
0

警告 如上所示,某些 RDBMS 将返回 2 行。其他人将返回行的笛卡尔积,即 A 行乘以 B 行。

一种棘手的方法是生成然后执行的 SQL

SELECT "update B set b.b_amount = ", a.amount, ", b.b_date = ", a.date, 
" where b.id = ", a.b_id
FROM A LEFT JOIN B ON B.id=A.b_id WHERE A.b_id>0 GROUP BY B.id

现在添加批处理终止符并执行此 SQL。查询结果应如下所示

 update B set b.b_amount = 200, b.b_date = 6/31/2012 where b.id = 1 

 update B set b.b_amount = 400, b.b_date = 6/29/2012 where b.id = 3 

注意:一些 RDBMS 会以不同的方式处理日期。有些需要引号。

于 2012-06-04T22:02:59.227 回答