【问题标题】:How to use CASE function in ORDER BY?如何在 ORDER BY 中使用 CASE 函数?
【发布时间】:2016-01-12 03:21:10
【问题描述】:

我的朋友几次前问过question。还有一个答案,这很好,但不适用于我的情况。该解决方案的想法是将当前表连接到自身。这对我来说似乎很昂贵且无效,因为实际上在我的查询中这些表上有四个joinvotesfavoritescommentsviewed)。

现在我想知道,如何使用CASE 函数来做到这一点?像这样的:

... ORDER BY Type, CASE WHEN AcceptedAnswerId = Id THEN 1 ELSE 0, timestamp

或者有没有更好的解决方案?


为了更具可读性,我将这些示例粘贴在这里:

我有一张这样的桌子:

// Mytable
+----+--------------------+------+------------------+-----------+
| Id |  QuestionOrAnswer  | Type | AcceptedAnswerId | timestamp |
+----+--------------------+------+------------------+-----------+
| 1  | question1          | 0    | 3                | 1         |
| 2  | answer1            | 1    | NULL             | 2         |
| 3  | answer2            | 1    | NULL             | 3         | -- accepted answer
| 4  | answer3            | 1    | NULL             | 4         |
+----+--------------------+------+------------------+-----------+

现在我想要这个结果:(请关注订单)

+----+--------------------+------+------------------+-----------+
| Id |  QuestionOrAnswer  | Type | AcceptedAnswerId | timestamp |
+----+--------------------+------+------------------+-----------+
| 1  | question1          | 0    | 3                | 1         |
| 3  | answer2            | 1    | NULL             | 3         | -- accepted answer 
| 2  | answer1            | 1    | NULL             | 2         |
| 4  | answer3            | 1    | NULL             | 4         |
+----+--------------------+------+------------------+-----------+
//                          ^ 0 means question and 1 means answer

【问题讨论】:

  • 您能否在问题中包含您当前尝试使用的 SQL?
  • @VolkerK 该架构不完整。实际上有一个related 列将相关问题和答案链接在一起。
  • @VolkerK 你为什么删除你的答案?你的小提琴很棒..!无论如何,我对你的小提琴有一个小问题。正如我所说,实际上我有一个名为related 的列,其中包含确定相关的帖子。现在我用问题的id 填充该列。我的意思是所有答案的列加上问题ID的问题填充。那样可以么?或者我可以存储其他内容来链接相关帖子(问题和答案)
  • @VolkerK 我明白了,谢谢。
  • 抱歉,没有更多关于这个问题的想法。

标签: mysql sql-order-by


【解决方案1】:

CASE 可以,但您缺少END。但在这种情况下,您也可以只使用IF(AcceptedAnswerId = Id,1,0)

在您展示的简单案例中,您可以这样做:

order by type,if(type=0,(@accepted:=acceptedanswerid),id<>@accepted),timestamp

但我不知道这是否适用于您的实际情况。

【讨论】:

  • 我在CASE 函数的末尾添加了END,现在没有任何语法错误。谢谢。但仍然排序不起作用。我想要这个顺序:1.问题,2.接受的答案 3.根据timestamp 的其他答案。我该怎么做?
  • 通过加入,如另一个问题的答案所示。或更改您的数据,以便答案中有一些列表明它已被接受。或将问题和答案放在单独的表格中;这似乎是你问题的根源。
  • 是的,在 order by 中使用变量使其取决于在排序之前最初读取行的顺序。这就是我强调我的解决方案仅适用于您提出的简单案例的原因之一,不一定适用于您更复杂的实际案例。我建议你加入。并向我们​​展示您的真实查询和真实架构(包括索引),以便我们向您保证它将是有效的或建议对您的索引/查询进行更改。
  • 那个 join 假设链接是相反的。这有效(一旦问题的类型设置为 1!):select t.* from mytable t left join mytable tquestion on t.type=1 and tquestion.acceptedanswerid=t.id order by t.type, tquestion.id is not null desc, t.timestamp 但可以在接受的答案ID 上使用索引
  • 不,如果问题是已接受的答案,它会阻止它尝试查找。但如果你删除它不会改变结果
【解决方案2】:

给定表定义(没有适当的索引)+样本数据

CREATE TABLE Table1
    (`Id` int, `QuestionOrAnswer` varchar(9), `Type` int, `AcceptedAnswerId` varchar(4), `related` int NOT NULL, `timestamp` int)
;

INSERT INTO Table1
    (`Id`, `QuestionOrAnswer`, `Type`, `AcceptedAnswerId`, `related`, `timestamp`)
VALUES
    (1, 'question1', 0, '3', 1, 1),
    (2, 'answer1', 1, NULL, 1, 2),
    (3, 'answer2', 1, NULL, 1, 3),
    (4, 'answer3', 1, NULL, 1, 4)

你可以使用查询

SELECT
  t2.*
FROM
  table1 as t1
JOIN
  table1 as t2
 ON
   t1.related=t2.related
 WHERE
   t1.related = 1
   AND t1.Type = 0
 ORDER BY
   t2.Type desc, t2.Id=t1.AcceptedAnswerId, t2.Id

获取特定问题的问题/答案集(t1.related = 1 不,使用正确的索引,这个查询并不“昂贵”。

http://sqlfiddle.com/#!9/24954/4 的示例(是的,我尝试了 4 次才正确,grrrrr)

【讨论】:

  • 谢谢,+1 ...但实际上您的解决方案是duplicate,我在问题中提到我不想自己加入表格。因为其他表上有四个连接,并且添加一个新连接似乎没有优化。
  • “似乎没有优化” - 为什么?只需以中间结果集快速变小的方式排列 JOIN。
  • 好吧,让我比较一下使用join 和使用if 的性能(如上面的答案) 我会告诉你为什么我说join 没有优化。
  • 老实说,差别不大。对于 1000 个请求,您的解决方案耗时 4.6 秒,而上述解决方案耗时 3.2 秒 ..!无论如何,好的,谢谢
  • 是的,最后我得出这个结论,在这种情况下使用join 是最好的选择。但是您的表结构存在一个大问题。我认为不可能向INSERT 写一个查询。为什么?因为我们无法将related 值填充到与其id 值完全相同的值。我们可以吗?怎么样?
猜你喜欢
  • 1970-01-01
  • 2012-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-17
  • 1970-01-01
相关资源
最近更新 更多