MariaDB / MySQL RANK()实现

时间:2015-10-30 11:41:59

标签: mysql sql mariadb rank

我正在从MS SQL Server迁移到 MariaDB 10.0 。我有查询使用RANK()PARTITION BY。我已经在我的桌子上创建了某种RANK()实现,但它无法正常工作。

原始查询是:

RANK() OVER (PARTITION BY visits.id_partner ORDER BY visits.updated_at DESC) AS rank

我对MariaDB / MySQL的实现:

SELECT
    ...,
    (
        CASE visits.id_partner
            WHEN @currId THEN
                @curRow := @curRow + 1
            ELSE
                @curRow := 1 AND @currId := visits.id_partner
        END
    ) AS rank
FROM
    records rec
    JOIN visits ON visits.id = rec.id_visit,
    (
        SELECT
        @curRank := 0,
        @currId := NULL
    ) r
WHERE
    ...
ORDER BY visits.id_partner ASC, visits.updated_at DESC

我想通过updated_at字段选择按id_partner顺序排名的行。当id_partner与RANK应该增加1之前的行相同时。当它与之前不同时,它应该重置为1.

但我的查询根本不起作用。我仍然在所有行上排名第一。你能帮我找错吗?

谢谢你的帮助!

1 个答案:

答案 0 :(得分:2)

在MySQL / MariaDB中使用变量很棘手。变量只能在一个语句中使用和分配(正如您所做的那样)。但是,ROW_NUMBER()可以使变量赋值短路。

我为RANK()使用这样的结构。 DENSE_RANK()实际上有点痛苦。 。 。 ROW_NUMBER()SELECT ..., (@rn := if(@currId = visits.id_partner, @rn + 1, if(@currId := visits.id_partner, 1, 1) ) ) as rank FROM records rec JOIN visits ON visits.id = rec.id_visit CROSS JOIN (SELECT @rn := 0, @currId := NULL) params WHERE ... ORDER BY visits.id_partner ASC, visits.updated_at DESC; 更简单。但是,这似乎是您的目标代码:

SELECT . . .,
       (@rn := if(@currId = visits.id_partner, @rn + 1,
                  if(@currId := visits.id_partner, 1, 1)
                 )
       ) as rank
FROM (SELECT ...
      FROM records rec JOIN
           visits
           ON visits.id = rec.id_visit 
      WHERE
          ...
      ORDER BY visits.id_partner ASC, visits.updated_at DESC
     ) t CROSS JOIN
     (SELECT @rn := 0, @currId := NULL) params;

编辑:

在MySQL中(可能在MariaDB中),除非使用子查询,否则有时变量不能正常工作。所以,试试这个:

{{1}}