我有两张桌子:
stock:
pid name qty
--- ---- ---
1 aaaa 2
2 bbbb 3
1 aaaa 5
3 cccc 1
2 bbbb 2
stock_total:
pid name total_qty
--- ---- ---------
我可以使用此查询将stock
表中的行与总数量插入stock_total
INSERT INTO stock_total (pid, name, total_qty)
SELECT pid, name, SUM(qty)
FROM stock
GROUP BY pid, name
问题是,我将通过cron job运行上面的SQL。因此,在下一次执行时,SQL应该更新现有产品并插入不存在的产品。
如果我遍历SELECT结果,检查每一行是否存在于stock_total
并执行INSERT或UPDATE,这将是非常低效的。
有没有更简单的方法来实现这一目标?也许通过修改上面的SQL。感谢。
答案 0 :(得分:1)
使用DUPLICATE KEY UPDATE
:
INSERT INTO TABLENAME(col1, col2)
VALUES (@value, ‘yyy’)
ON DUPLICATE KEY UPDATE col1 = @value
答案 1 :(得分:1)
这是更新:
UPDATE stock_total
SET total_qty = SUM(s.qty)
FROM stock_total st
INNER JOIN stock s
ON st.pid = s.pid
AND st.name = s.name
WHERE s.pid = st.pid
GROUP BY s.pid
这是插入:
INSERT INTO stock_total
SELECT s.pid, s.name, SUM(s.qty)
FROM stock s
WHERE s.pid NOT IN (SELECT pid FROM stock_total)
GROUP BY s.pid, s.name
应该没问题,试一试。
答案 2 :(得分:0)
为什么不从工作中调用存储过程?
在块中的SP中捕获DUPLICATE KEY
例外和UPDATE
。如果没有抛出EXCEPTION
,它将INSERT
。
答案 3 :(得分:0)
merge
正是您要搜索的内容。使用方法如下 -
merge into stock_total s " +
"using (select ? pid, ? name, ? total_qty from dual) d " +
"on (s.pid = d.pid and s.name = d.name and s.total_qty = d.total_qty) " +
"when matched then " +
"update set s.pid= d.pid, s.name = d.name, s.total_qty = d.total_qty" +
"when not matched then " +
"insert (pid, name, total_qty) " +
"values(d.pid, d.name, d.total_qty)" ;
编辑(对于mySQL):
MERGE INTO table_name WITH (HOLDLOCK) USING table_name ON (condition)
WHEN MATCHED THEN UPDATE SET column1 = value1 [, column2 = value2 ...]
WHEN NOT MATCHED THEN INSERT (column1 [, column2 ...]) VALUES (value1 [, value2 ...])
答案 4 :(得分:0)
经过一些谷歌搜索并在这里试验答案后,我想出了这个解决方案。事实证明,MySQL支持REPLACE INTO...
和...ON DUPLICATE KEY UPDATE
。所以我的查询是这样的:
REPLACE INTO stock_total
SELECT pid, name, SUM(qty)
FROM stock
GROUP by pid, name
,或者
INSERT INTO stock_total
SELECT pid, name, SUM(qty)
FROM stock
GROUP by pid, name
ON DUPLICATE KEY UPDATE total_qty=VALUES(total_qty)
如果stock_total
上存在一行,则第一个查询将删除然后插入新行,
第二个查询将更新现有行。
只有当表具有主键或唯一索引时,两个查询才有效:
CREATE TABLE stock_total (
pid INT NOT NULL,
name VARCHAR(20) NOT NULL,
total_qty INT NOT NULL,
UNIQUE (pid, name)
);
文档: