Mysql:从子查询中按最大N值排序

Tom*_*röm 8 mysql sql

我准备好了.

前言:我想用任何N做这个工作,但为了简单起见,我将N设置为3.

我有一个查询(特别是MySQL)需要从表中提取数据并根据该表中的前3个值进行排序,然后再回退到其他排序条件.

所以基本上我有这样的东西:

SELECT tbl.id 
FROM
  tbl1 AS maintable 
  LEFT JOIN 
  tbl2 AS othertable 
  ON
  maintable.id = othertable.id
ORDER BY 
  othertable.timestamp DESC, 
  maintable.timestamp DESC
Run Code Online (Sandbox Code Playgroud)

这是所有基本的教科书.但问题是我需要第一个ORDER BY子句才能获得othertable.timestamp中的三个最大值,然后回退到maintable.timestamp.

另外,执行LIMIT 3子查询以进行其他操作并加入它是不行的,因为这需要处理应用于维护的任意数量的WHERE条件.

我几乎能够使用这样的基于用户变量的方法,但它失败了,因为它没有考虑到排序,因此它将获得它找到的第一个三个其他值:

ORDER BY 
  (
    IF(othertable.timestamp IS NULL, 0, 
      IF(
        (@rank:=@rank+1) > 3, null, othertable.timestamp
      )
    )
  ) DESC
Run Code Online (Sandbox Code Playgroud)

(声明前面有@rank:= 0)

那么......有关于此的任何提示吗?我对这个问题失去了理智.我对此的另一个参数是,因为我只是在改变现有的(非常复杂的)查询,所以我不能执行包装外部查询.另外,如上所述,我使用MySQL,因此任何使用ROW_NUMBER函数的解决方案都是不可及的.

感谢所有提前.

编辑.这里有一些带有时间戳的示例数据,这些数据简化为更简单的整数,以说明我需要的内容:

maintable

id      timestamp
1       100
2       200
3       300
4       400
5       500
6       600

othertable

id     timestamp
4      250
5      350
3      550
1      700

=>

1
3
5
6
4
2
Run Code Online (Sandbox Code Playgroud)

如果由于某种原因我们在查询中添加WHERE NOT maintable.id = 5,这是我们应该得到的:

1
3
4
6
2
Run Code Online (Sandbox Code Playgroud)

...因为现在4是参考这个集合的前三个值之一.

如您所见,来自othertable的id为4的行不包含在排序中,因为它是时间戳值降序的第四行,因此它会回退到按基本时间戳排序.

现实世界对此的需求是这样的:我有"维护"的内容,"othertable"基本上是特色内容的标记,时间戳为"特色日期".我有一个视图,我应该将最后3个特色项目浮动到顶部,列表的其余部分只是一个反向的时间顺序列表.

Gol*_*rol 1

也许是这样的。

SELECT
  id
FROM
  (SELECT 
    tbl.id,
    CASE WHEN othertable.timestamp IS NULL THEN 
      0 
    ELSE 
      @i := @i + 1
    END AS num,
    othertable.timestamp as othertimestamp,
    maintable.timestamp as maintimestamp
  FROM
    tbl1 AS maintable
    CROSS JOIN (select @i := 0) i 
    LEFT JOIN tbl2 AS othertable 
      ON maintable.id = othertable.id
  ORDER BY
    othertable.timestamp DESC) t
ORDER BY
  CASE WHEN num > 0 AND num <= 3 THEN
    othertimestamp
  ELSE
    maintimestamp
  END DESC
Run Code Online (Sandbox Code Playgroud)