【问题标题】:Put a specific row first and then order by a column先放一个特定的行,然后按列排序
【发布时间】:2014-12-29 17:51:03
【问题描述】:

编辑:目标是对输出进行排序,以便第一个结果是 store_id = 5 的行和 store_id = 5 的所有项目的最大排名。然后,其余交易根据其排名按降序排列订单,无论他们的 store_id 是什么。对于实际的查询,联合的代价太高了。

数据示例如下:

+----+----------+------+
| id | store_id | rank |
+----+----------+------+
|  1 |   1      |  10  |
+----+----------+------+
|  2 |   5      |   9  |
+----+----------+------+
|  3 |   4      |   8  |
+----+----------+------+
|  4 |   3      |   7  |
+----+----------+------+
|  5 |   3      |   6  |
+----+----------+------+
|  6 |   1      |   5  |
+----+----------+------+

最终运行的查询是:

SELECT id,store_ID,IF(@id=id,rank=rank*9999999,rank) AS rank
FROM (
    SELECT * FROM (
        SELECT id,rank,store_id
        FROM items
    ) b
    JOIN (@id:=(SELECT id FROM b WHERE store_id = 5 ORDER BY rank DESC LIMIT 1)) AS s
)
ORDER BY rank DESC

期望的结果是:

+----+----------+------+
| id | store_id | rank |
+----+----------+------+
|  2 |   5      |   9  |
+----+----------+------+
|  1 |   1      |  10  |
+----+----------+------+
|  3 |   4      |   8  |
+----+----------+------+
|  4 |   3      |   7  |
+----+----------+------+
|  5 |   3      |   6  |
+----+----------+------+
|  6 |   1      |   5  |
+----+----------+------+

此处 (@id:=(SELECT id FROM b WHERE store_id = 5 ORDER BY rank DESC LIMIT 1)) 用于选择 store_id = 5 得分最高的项目。该项目应出现在列表的首位,因此为什么通过将它乘以一个非常大的数字来重新排列它。所有其他排名保持不变,并根据其分数按降序排列。

问题是连接中的 select 语句试图连接来自名为 b 的子查询的选择。但是,表b实际上并不存在于数据库中,所以MySQL说表b不存在。如何引用子查询?实际的子查询非常复杂,所以我没有在此处包含它,但如果有兴趣,您可以在此处查看它的一个版本:MySQL - How To Optimize thie Query。这个问题中的查询只是为了让问题简单。

【问题讨论】:

  • 你能不能用一些数据做一个例子,我真的不明白你想要得到什么
  • 我已经更新了问题
  • 您能举例说明您要完成的工作吗?到目前为止,我不知道你想做什么。
  • 您可以添加另一个代表计算排名的 non-existing 列,如果 store_id 为 5,则它的值为 2,否则为 1。然后您需要做的就是更改 ORDER BY computedRank, rank DESC
  • 两个问题可能是你的问题。 1) 为什么你有FROM( FROM(?您是否缺少加入的 ON 子句?

标签: mysql sql sql-order-by


【解决方案1】:

您可以调整 order by 子句以将特定行放在首位。假设您希望 store_id 5 排在第一位,您可以这样做:

ORDER BY store_id = 5 DESC, rank DESC;

这会将 store_id 为 5 的行放在顶部。在此示例中,您希望 store_id 5 的排名最高的行,因此我编写了以下子查询:

SELECT id
FROM myTable
WHERE store_id = 5
ORDER BY rank DESC
LIMIT 1;

我把它放在 ORDER BY 子句中:

SELECT *
FROM myTable
ORDER BY id = 
      (SELECT id FROM myTable WHERE store_id = 5 ORDER BY rank DESC LIMIT 1) DESC, 
   rank DESC;

这是SQL Fiddle

编辑

如果您在 FROM 子句中放置子查询,您将无法在 ORDER BY 子句的子查询中引用其别名。但是,以一种非常难以理解的方式,您可以将相同的子查询放在那里来完成它,如下所示:

SELECT *
FROM (SELECT * FROM myTable) b
ORDER BY id = 
   (SELECT id FROM (SELECT * FROM myTable) b WHERE store_id = 5 ORDER BY rank DESC LIMIT 1) DESC, 
   rank DESC;

另一个Fiddle

【讨论】:

  • 我喜欢这个方案,但问题是我需要从子查询生成的表b中选择。由于我的数据库中不存在 b,我收到以下错误消息:表 'b' 不存在
  • 这是因为这篇文章是一个过于简化的查询版本,它实际上通过一系列衰减和距离函数计算排名。因此,它必须通过基于此子查询的选择来确定订单,b.
  • 我的查询顺序不是基于子查询的结果吗?我知道我给出的解决方案与您的查询不同,但它确实回答了问题,不是吗?
  • 它确实会产生所需的输出。我遇到的问题是试图让它在子查询上工作,这是实际应用程序的要求。 SQL Fiddle 中的示例查询将是 SELECT * FROM (SELECT * FROM myTable) b ORDER BY id = (SELECT id FROM b WHERE store_id = 5 ORDER BY rank DESC LIMIT 1) DESC, rank DESC;
  • @user2694306 我想我只是不明白你为什么需要那个子查询,它没有做任何特别的事情。此外,它不应该工作,因为您正在创建两个无法相互访问的独立子查询。
猜你喜欢
  • 1970-01-01
  • 2023-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-17
  • 2020-09-03
相关资源
最近更新 更多