SQL order by maintain variable order

SQL order by maintain variable order

我创建了一个按分数排序的排名查询,然后如果是平局则按创建日期排序。问题是当我使用日期来订购抽奖时,它变得一团糟。

这是我的第一个:

SELECT 
    @rownum := @rownum + 1 AS rank,
    sticker_id,
    total_shared,
    total_liked,
    total_used,
    total_shared+total_liked+total_used AS points,
    stickers.date
FROM( 
    SELECT 
        sticker_id,
        SUM(if(event_id = 1, 4, 0)) AS total_shared,
        SUM(if(event_id = 2, 2, 0)) AS total_liked,
        SUM(if(event_id = 3, 6, 0)) AS total_used
    FROM stickers_stats
    WHERE timestamp LIKE '2015-09%'
    GROUP BY sticker_id
) AS ranks 
JOIN (SELECT @rownum := 0) r
INNER JOIN stickers
    ON ranks.sticker_id = stickers.id
ORDER BY points DESC

结果:


这是我得到的:

SELECT 
    @rownum := @rownum + 1 AS rank,
    sticker_id,
    total_shared,
    total_liked,
    total_used,
    total_shared+total_liked+total_used AS points,
    stickers.date
FROM( 
    SELECT 
        sticker_id,
        SUM(if(event_id = 1, 4, 0)) AS total_shared,
        SUM(if(event_id = 2, 2, 0)) AS total_liked,
        SUM(if(event_id = 3, 6, 0)) AS total_used
    FROM stickers_stats
    WHERE timestamp LIKE '2015-09%'
    GROUP BY sticker_id
) AS ranks 
JOIN (SELECT @rownum := 0) r
INNER JOIN stickers
    ON ranks.sticker_id = stickers.id
ORDER BY points DESC, stickers.date ASC

结果:

我试过更改字段的显示顺序和所有内容,但找不到解决方案。如何按 pointsstickers.date 以新排名位置排序?

当您开始将变量与其他结构混合时,

MySQL 可能会感到困惑。我不确定你的查询有什么提示,但使用子查询应该有所帮助:

SELECT @rownum := @rownum + 1 AS rank, t.*
FROM (SELECT sticker_id, total_shared, total_liked, total_used,
             (total_shared + total_liked + total_used) AS points,
             s.date
      FROM (SELECT sticker_id,
                   SUM(if(event_id = 1, 4, 0)) AS total_shared,
                   SUM(if(event_id = 2, 2, 0)) AS total_liked,
                   SUM(if(event_id = 3, 6, 0)) AS total_used
            FROM stickers_stats
            WHERE timestamp >= '2015-09-01' and timestamp < '2015-10-01'
            GROUP BY sticker_id
          ) r JOIN
          stickers s
          ON r.sticker_id = s.id 
     ) t CROSS JOIN
     (SELECT @rownum := 0) params
ORDER BY points DESC, date ASC;

还有:

  • 不要将 LIKE 用于 date/time 值。
  • 总是在 JOIN 中使用 ON 子句。如果你想要 CROSS JOIN,请明确。

我倾向于在子查询中强制排序。它仍然不确定是否有效(MySQL 有一些关于订单语句的 get out 子句将在查询中执行),但似乎更可靠。

在这种情况下,我建议您在子查询中也加入贴纸:-

SELECT 
    @rownum := @rownum + 1 AS rank,
    sticker_id,
    total_shared,
    total_liked,
    total_used,
    total_shared+total_liked+total_used AS points,
    stickers_date
FROM( 
    SELECT 
        sticker_id,
        stickers.date AS stickers_date,
        SUM(if(event_id = 1, 4, 0)) AS total_shared,
        SUM(if(event_id = 2, 2, 0)) AS total_liked,
        SUM(if(event_id = 3, 6, 0)) AS total_used
    FROM stickers_stats
    INNER JOIN stickers
    ON stickers_stats.sticker_id = stickers.id
    WHERE YEAR(timestamp) = 2015
    AND MONTH(timestamp) = 9 
    GROUP BY sticker_id, stickers_date
    ORDER BY points DESC, stickers_date ASC
) AS ranks 
CROSS JOIN (SELECT @rownum := 0) r
ORDER BY points DESC, stickers.date ASC