高级SQLite更新表查询

时间:2012-06-04 14:22:04

标签: sqlite

我正在尝试更新数据库的表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;

2 个答案:

答案 0 :(得分: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不支持这一点,因为this可能是相关的问题点。但是,使用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 JOIN而不是LEFT JOIN时,您可以完全删除WHERE子句。星展银行将解决所有不满意的关系。

答案 1 :(得分: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将以不同方式处理日期。有些需要报价。