有桌子照片
photos.id
photos.user_id
photos.order
A)是否可以通过单个查询按用户对所有照片进行分组,然后更新订单1,2,3..N?
B)添加了扭曲,如果某些照片已经关联了订单价值怎么办?确保新的照片。订单永远不会重复,并填写低于或高于现有的蚂蚁订单(尽可能最好)
我唯一的想法就是在这上面运行一个脚本并循环遍历并重新排序所有内容?
photos.id int(10)
photos.created_at datetime
photos.order int(10)
photos.user_id int(10)
现在数据可能如下所示
user_id = 1
photo_id = 1
order = NULL
user_id = 2
photo_id = 2
order = NULL
user_id = 1
photo_id = 3
order = NULL
期望的结果将是
user_id = 1
photo_id = 1
order = 1
user_id = 2
photo_id = 2
order = 1
user_id = 1
photo_id = 3
order = 2
答案 0 :(得分:11)
<强> A)强>
您可以使用随每行递增的变量,并使用每个user_ID重置以获取行数。
SELECT ID,
User_ID,
`Order`
FROM ( SELECT @r:= IF(@u = User_ID, @r + 1,1) AS `Order`,
ID,
User_ID,
@u:= User_ID
FROM Photos,
(SELECT @r:= 1) AS r,
(SELECT @u:= 0) AS u
ORDER BY User_ID, ID
) AS Photos
<强> B)强>
我的第一个解决方案是将Order
添加到添加行号的排序中,因此任何带有Order
的内容首先按其顺序排序,但这只适用于您的订购系统没有的情况差距从1开始:
SELECT ID,
User_ID,
RowNumber AS `Order`
FROM ( SELECT @r:= IF(@u = User_ID, @r + 1,1) AS `RowNumber`,
ID,
User_ID,
@u:= User_ID
FROM Photos,
(SELECT @i:= 1) AS r,
(SELECT @u:= 0) AS u
ORDER BY User_ID, `Order`, ID
) AS Photos
ORDER BY `User_ID`, `Order`
订购差距
我最终找到了一种维持排序顺序的方法,即使序列中存在间隙也是如此。
SELECT ID, User_ID, `Order`
FROM Photos
WHERE `Order` IS NOT NULL
UNION ALL
SELECT Photos.ID,
Photos.user_ID,
Numbers.RowNum
FROM ( SELECT ID,
User_ID,
@r1:= IF(@u1 = User_ID,@r1 + 1,1) AS RowNum,
@u1:= User_ID
FROM Photos,
(SELECT @r1:= 0) AS r,
(SELECT @u1:= 0) AS u
WHERE `Order` IS NULL
ORDER BY User_ID, ID
) AS Photos
INNER JOIN
( SELECT User_ID,
RowNum,
@r2:= IF(@u2 = User_ID,@r2 + 1,1) AS RowNum2,
@u2:= User_ID
FROM ( SELECT DISTINCT p.User_ID, o.RowNum
FROM Photos AS p,
( SELECT @i:= @i + 1 AS RowNum
FROM INFORMATION_SCHEMA.COLLATION_CHARACTER_SET_APPLICABILITY,
( SELECT @i:= 0) AS i
) AS o
WHERE RowNum <= (SELECT COUNT(*) FROM Photos P1 WHERE p.User_ID = p1.User_ID)
AND NOT EXISTS
( SELECT 1
FROM Photos p2
WHERE p.User_ID = p2.User_ID
AND o.RowNum = p2.`Order`
)
AND p.`Order` IS NULL
ORDER BY User_ID, RowNum
) AS p,
(SELECT @r2:= 0) AS r,
(SELECT @u2:= 0) AS u
ORDER BY user_ID, RowNum
) AS numbers
ON Photos.User_ID = numbers.User_ID
AND photos.RowNum = numbers.RowNum2
ORDER BY User_ID, `Order`
但是你可以看到这很复杂。这可以通过将具有order
值的那些值分别处理为没有值的那些来实现。顶部查询只按照每个用户的ID顺序对所有没有order
值的照片进行排名。底部查询使用交叉连接为每个用户ID生成从1到n的顺序列表(最多为每个User_ID的条目数)。所以使用这样的数据集:
ID User_ID Order
1 1 NULL
2 2 NULL
3 1 NULL
4 1 1
5 1 3
6 2 2
7 2 3
会生成
UserID RowNum
1 1
1 2
1 3
1 4
2 1
2 2
2 3
然后使用NOT EXISTS
来消除Photos已使用的非空order
的所有组合,并按User_ID分区的RowNum顺序排列
UserID RowNum Rownum2
1 2 1
1 4 2
2 1 1
然后可以将RowNum2值与from子查询中获得的rownum值匹配,给出正确的order
值。啰嗦,但它确实有效。
<强> Example on SQL Fiddle 强>
答案 1 :(得分:0)
为我工作。我需要将 version 分组增加4个字段(主机,文件夹,文件名,状态),并按1排序( downloadedAtTicks )。 这是我的 SELECT
SET @status := NULL;
SET @version := NULL;
SELECT
id,
host,
folder,
fileName,
status,
downloadedAtTicks,
version,
IF(IF(status IS NULL, 0, status) = @status, @version := @version + 1, @version := 0) AS varVersion,
@status := IF(status IS NULL, 0, status) AS varStatus
FROM csvsource
ORDER BY host, folder, fileName, status, downloadedAtTicks;
这是我的更新
SET @status := NULL;
SET @version := NULL;
UPDATE
csvsource csv,
(SELECT
id,
IF(IF(status IS NULL, 0, status) = @status, @version := @version + 1, @version := 0) AS varVersion,
@status := IF(status IS NULL, 0, status) AS varStatus
FROM csvsource
ORDER BY host, folder, fileName, status, downloadedAtTicks) AS sub
SET
csv.version = sub.varVersion
WHERE csv.id = sub.id;