我有几组数据。每个组都有一个property
字段。
例如:
_________________________
| id | value | property |
--------------------------
| 1 | 2 | 3 |
--------------------------
| 2 | 2 | 3 |
--------------------------
| 3 | 2 | 3 |
--------------------------
| 4 | 2 | 4 |
-------------------------
| 5 | 2 | 4 |
--------------------------
| 6 | 2 | 4 |
--------------------------
如何通过id ASC
更新由property = 3
排序的两个字符串,并通过一个查询更新id ASC
和property = 4
排序的2个字符串?
我希望使用property = 3
更新3行中的2行,并使用property = 4
更新3行中的2行。例如:id为1和2的行,id为4和5的行
即我希望通过一次查询更新不同条件的数据组
答案 0 :(得分:2)
您可以使用计算的排名字段来执行此操作,例如 -
SELECT p1.*, COUNT(*) rank FROM properties p1
LEFT JOIN properties p2
ON p2.property = p1.property AND p2.id <= p1.id
GROUP BY p1.property, p1.id
此查询将返回带有row-number by属性的数据集:
+------+-------+----------+------+
| id | value | property | rank |
+------+-------+----------+------+
| 1 | 2 | 3 | 1 |
| 2 | 2 | 3 | 2 |
| 3 | 2 | 3 | 3 |
| 4 | 2 | 4 | 1 |
| 5 | 2 | 4 | 2 |
| 6 | 2 | 4 | 3 |
+------+-------+----------+------+
然后你应该更新排名&lt;的记录3:
UPDATE properties p
JOIN (SELECT p1.*, COUNT(*) rank FROM properties p1
LEFT JOIN properties p2
ON p2.property = p1.property AND p2.id <= p1.id
GROUP BY p1.property, p1.id) r
ON p.id = r.id
SET p.value = 100 -- set new value here
WHERE r.rank < 3
答案 1 :(得分:1)
我假设您的意思是将两个更新限制为每行两行。您可以在更新语句中使用ORDER BY
和LIMIT
:
UPDATE yourtable
SET property = 'new_value'
WHERE value=2 AND property = 4
ORDER BY id ASC LIMIT 2
UPDATE yourtable
SET property = 'new_value'
WHERE value=2 AND property = 3
ORDER BY id DESC LIMIT 2
要将此强制转换为一个查询,您需要JOIN
针对通过UNION
检索要更新的ID的子查询。我认为这是合法的:
UPDATE yourtable
JOIN (
(SELECT id FROM yourtable WHERE value=2 AND property=4 ORDER BY id ASC LIMIT 2)
UNION ALL
(SELECT id FROM yourtable WHERE value=2 AND property=3 ORDER BY id DESC LIMIT 2)
) updaterows ON yourtable.id = updaterows.id
SET property = 'new value'
答案 2 :(得分:1)
以下是解决方案,请参阅以下讨论:
update
t,
(select GROUP_CONCAT(ids) as matching_ids from (
select
SUBSTRING_INDEX(GROUP_CONCAT(id order by id), ',', 2) AS ids
from
t
where
property in (3,4)
group by
property
) s1
) s2
set value=12345
where
FIND_IN_SET(id, matching_ids) > 0
;
为了说明并假设您的表名为t
,初始状态为:
root@mysql-5.1.51> select * from t;
+----+-------+----------+
| id | value | property |
+----+-------+----------+
| 1 | 2 | 3 |
| 2 | 2 | 3 |
| 3 | 2 | 3 |
| 4 | 2 | 4 |
| 5 | 2 | 4 |
| 6 | 2 | 4 |
+----+-------+----------+
运行此查询的结果是:
root@mysql-5.1.51> select * from t;
+----+-------+----------+
| id | value | property |
+----+-------+----------+
| 1 | 12345 | 3 |
| 2 | 12345 | 3 |
| 3 | 2 | 3 |
| 4 | 12345 | 4 |
| 5 | 12345 | 4 |
| 6 | 2 | 4 |
+----+-------+----------+
查询的简要说明:
我使用id
语句为每个属性选取前两个SUBSTRING_INDEX(GROUP_CONCAT(id order by id), ',', 2)
。
我使用GROUP_CONCAT(ids) as matching_ids
结合上述内容以获取所有有效的id
。
最后,我更新表格中id
在合并matching_ids
文字内的所有行。
备注:强>
您应该验证group_concat_max_len
变量足够长。默认值为 1024 。无论如何,你很可能想要数百万(无论我的答案如何)。
查询远非最佳。它回答了您的问题,但您无法在此处获得最佳查询。
对于包含两个或三个查询的交易,您最好的情况更好。