5

有一张桌子照片

photos.id
photos.user_id
photos.order

A)是否可以通过单个查询按用户对所有照片进行分组,然后更新顺序 1,2,3..N ?

B)增加了扭曲,如果某些照片已经具有关联的订单价值怎么办?确保新的 photos.order 永远不会重复,并填写低于或高于现有订单的蚂蚁订单(尽可能)

我唯一的想法就是在上面运行一个脚本并循环遍历它并重新“排序”所有内容?

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
4

2 回答 2

12

一种)

您可以使用随每一行递增并随每个 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

SQL Fiddle 示例

二)

我的第一个解决方案是添加Order到添加行号的排序中,因此任何具有OrderGets 的内容首先按其顺序排序,但这仅在您的排序系统没有间隙并且从 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`

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价值的人与没有价值的人分开对待而起作用的。order最上面的查询只是按照每个用户的 ID 顺序排列所有没有值的照片。底部查询使用交叉连接为每个用户 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非 null 来消除 Photos 已经使用的所有组合order,并按由 User_ID 划分的 RowNum 的顺序排列

UserID  RowNum  Rownum2
1       2       1
1       4       2
2       1       1

然后可以将 RowNum2 值与在 from 子查询中获得的 rownum 值匹配,从而给出正确的order值。长篇大论,但它的工作原理。

SQL Fiddle 示例

于 2012-06-11T16:18:36.613 回答
0

为我工作。我需要将版本分组增加 4 个字段(主机、文件夹、文件名、状态)并按 1 排序(下载的AtTicks )。这是我的选择

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;
于 2018-11-28T15:25:05.693 回答