【问题标题】:Is it possible to sort the order in which columns are returned in a mysql SELECT statement?是否可以对 mysql SELECT 语句中返回的列的顺序进行排序?
【发布时间】:2016-01-04 00:44:54
【问题描述】:

想象一下在线调查中的两个问题:

  1. 你喜欢苹果吗?

存储在 mysql db 列“q1”中的结果为 1 表示是或 0 表示否

  1. 你喜欢橘子吗?

存储在 mysql db 列“q2”中的结果为 1 表示是或 0 表示否

想象以下 SELECT 语句:

SELECT SUM(q1) AS q1Sum, SUM(q2) AS q2Sum FROM myTable

假设 q1Sum=10 和 q2Sum=12。当前的 SELECT 语句将返回:

+-------+-------+
| q1Sum | q2Sum |
+-------+-------+
|   10  |   12  |
+-------+-------+

但是是否可以返回不同的列顺序,以便最大的 SUM 始终是返回的第一列而不更改 SELECT 语句中的列表顺序?

SELECT SUM(q1) AS q1Sum, SUM(q2) AS q2Sum FROM myTable << something else >>

+-------+-------+
| q2Sum | q1Sum |
+-------+-------+
|   12  |   10  |
+-------+-------+

如果 q1Sum 大于 q2Sum,则返回的列顺序将恢复为原始顺序。

我为什么要问这个问题?

  1. 我从与上述类似的调查中继承了一个包含多个列的大型表格,其中对多个问题的回答是是=1 和否=0。我认为正确的方法是创建保存 SUM 值的变量并将它们插入临时表行,然后选择/排序返回的行。但是,这并不能真正回答“是否可以对返回的列进行排序”的问题,我什至不确定我的假设是否正确,“正确的方法”......
  2. 虽然我知道如何对返回的结果进行排序而不考虑顺序(在我的情况下使用 php),但我很好奇是否有一种方法可以自动对 mysql 中返回的列进行排序,以便最高值始终是第一列对于返回的剩余列,剩余列中的 SUM-ed 结果会以数字形式递减。
  3. 好奇是否有一个优雅的答案。虽然使用 ORDER BY 很容易对 mysql 中返回的 ROWS 进行排序,但我还没有看到如何对多个 SUM-ed 的单个返回行的 COLS 进行排序的示例如上所述的值。想象一下上面的 10 个问题而不是 2 个问题。我假设这是不可能的,但希望有人能证明我错了……以一种很好的方式。

【问题讨论】:

  • “否”。 查询的形状(结果列)是固定的。 IMOHO 的“正确”解决方案是规范化数据(通过设计或先前的查询结果) - 使问题变成 - 在对其进行操作之前。当作为查询的一部分完成时,这也称为“UNPIVOT”;它不一定需要临时表。

标签: mysql database sorting


【解决方案1】:

假设我正确理解您的问题,您可以使用case 声明:

SELECT CASE WHEN SUM(q1) > SUM(q2) THEN SUM(q1) ELSE SUM(q2) END AS q1Sum,
   CASE WHEN SUM(q1) > SUM(q2) THEN SUM(q2) ELSE SUM(q1) END AS q2Sum 
FROM myTable 

实际上,这会错误地标记列 - 如果不使用 dynamic sql,您将无法更改列的名称。

【讨论】:

    【解决方案2】:

    感谢@user2864740 和@sgeddes 的及时回复。

    SURVEY SAYS:如果不使用动态 sql,则无法使用 mysql 对 SELECT 语句中返回的列进行排序。

    我想出的解决方案使用临时表,类似于下面的示例。虽然可能不太理想,但它回复了我需要的邮件。好奇是否有更好的方法来做同样的事情,或者我是否在下面搞砸了其他任何事情。

    DROP TEMPORARY TABLE IF EXISTS orderedSums;
    SET @q1Sum = (SELECT SUM(q1) FROM myTable);
    SET @q2Sum = (SELECT SUM(q2) FROM myTable);
    
    CREATE TEMPORARY TABLE orderedSums (
        qNum VARCHAR(5),
        qSum INT
    );
    
    INSERT INTO orderedSums
        VALUES ('q1Sum', @q1Sum),('q2Sum', @q2Sum);
    
    SELECT qNum, qSum
        FROM orderedSums
        ORDER BY qSum DESC;
    

    从 myTable 返回按降序排序的多行 SUM。

    【讨论】:

    • 请考虑使用 unpivot。然后,您可以在没有临时表的单个查询中执行此操作。示例:stackoverflow.com/questions/15184381/….
    • 单次查询就可以得到等价的结果(不需要临时表)SELECT 'q1Sum' AS qNum, SUM(q1) AS qSum FROM myTable UNION ALL SELECT 'q2Sum', SUM(q2) FROM myTable ORDER BY 2 DESC
    • 谢谢@siride。这似乎提出了多行与多列(ref link) 的效率问题。就我而言,我正在为非常有限的用户群在有限的时间内创建一个简单的 SUM 总计仪表板。可能不值得 UNPIVOT 但非常有用的链接供将来参考。
    • 谢谢@spencer7593。这提出了临时表与联合 (ref link) 的问题。似乎最好使用 UNION ALL。对于多个问题,UNION ALL 可以用括号分开:(SELECT 'q1Sum' AS qNUM, SUM(q1) AS qSUM FROM myTable) UNION ALL (next q) UNION ALL (next q)...
    • 创建/填充/查询/删除临时表会产生开销。这是更多的工作。运行UNION ALL 会更有效率......它可以完成您需要完成的工作,而不会产生不必要的开销。在我的示例 UNION ALL 查询中,可以将括号包裹在 SELECT 语句周围,但在本示例中,这不是必需的,
    猜你喜欢
    • 2017-02-21
    • 2011-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多