如何在 SQL 中转置查询结果?

Posted

技术标签:

【中文标题】如何在 SQL 中转置查询结果?【英文标题】:How can I transpose a query result in SQL? 【发布时间】:2019-07-03 18:44:00 【问题描述】:

由于许多子查询,我有下表:

+---------------------------------------------+
| register | simulation | hasLimit | approved |
+---------------------------------------------+
|     X    |     Y      |    Z     |    W     |
+---------------------------------------------+

但我希望它是这样的:

+----------------+
| register   | X | 
+----------------+
| simulation | Y | 
+----------------+
| hasLimit   | Z | 
+----------------+
| approved   | W | 
+----------------+

在 R 中,我会简单地使用函数 t() 进行转置,但在 SQL 中似乎有点困难。我试图理解在这种情况下应用的函数 pivot ,但这似乎有点奇怪,因为我实际上只是在转置,而不是旋转任何东西。

【问题讨论】:

用您正在使用的 DBMS(SQL Server、Oracle、mysql 等)标记您的问题 Google 中的“Columns to Rows SQL”应该这样做。 之前已经在这里回答过:***.com/questions/18026236/sql-server-columns-to-rows 【参考方案1】:

您似乎想要一个“反透视”操作。

假设列的类型都兼容,可以使用union all

select 'register' as which, register as value union all
select 'simulation',  simulation union all
select 'hasLimit', hasLimit union all
select 'approved', approved;

有些数据库要求每个子查询都有一个FROM 子句,例如from dual

这是非常少量的数据。对于较大的数据,我更喜欢横向连接,但语法(及其可用性)取决于数据库。

【讨论】:

我一开始展示的表本身并不是一个表,它是许多并排查询的结果,我将所有查询放在一个查询中,每个单独的查询都给了我某个数字(X、Y、Z、W)。我想我必须使用 unpivot 函数,但在生成此结果的查询中找不到如何执行此操作 @EduardaOliveira 为了能够使用 unpivoting,我们需要确保您的 DBMS 产品适合它。即你需要先告诉你的 DBMS。【参考方案2】:

鉴于来自

的回报
         SELECT 'x' AS register
              , 'y' AS simulation
              , 'z' AS hasLimit
              , 'w' AS approved

我们可以将其包装在一组括号中,并在外部查询中将其作为内联视图引用。

例如:

SELECT CASE i.n
         WHEN 1 THEN 'register'
         WHEN 2 THEN 'simulation'
         WHEN 3 THEN 'hasLimit'
         WHEN 4 THEN 'approved'
       END AS col1
     , CASE i.n
         WHEN 1 THEN q.register
         WHEN 2 THEN q.simulation
         WHEN 3 THEN q.hasLimit
         WHEN 4 THEN q.approved
       END AS col2
  FROM (
         SELECT 'x' AS register
              , 'y' AS simulation
              , 'z' AS hasLimit
              , 'w' AS approved
       ) q
 CROSS
  JOIN ( SELECT 1 AS n
         UNION ALL SELECT 2
         UNION ALL SELECT 3
         UNION ALL SELECT 4
       ) i
 ORDER
    BY i.n

这似乎有点复杂,因为您已经有返回标量值的子查询,我们可以将它们与 UNION ALL 集合运算符结合起来

SELECT 'register'  AS col1, ( scalar_subquery_for_x ) AS col2
UNION ALL 
SELECT 'simulation'       , ( scalar_subquery_for_y )
UNION ALL 
SELECT 'hasLimit'         , ( scalar_subquery_for_z )
UNION ALL 
SELECT 'approved'         , ( scalar_subquery_for_w )

如果我们需要有保证的顺序,我们可以将整个内容包裹在括号中并添加 ORDER BY 子句。 (如果没有 ORDER BY,我们确实观察到行是从 UNION ALL“按顺序”返回的,但不能保证这种行为。)

【讨论】:

【参考方案3】:

如下使用简单的UNPIVOT

SELECT Col, Val
FROM <Your Table>
UNPIVOT (Val FOR Col IN([register],[simulation],[hasLimit],[approved])) unpiv

【讨论】:

以上是关于如何在 SQL 中转置查询结果?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Oracle 中转置? [复制]

NamedParameterJdbcTemplate Oracle SQL,如何在命名查询中转义单引号?

sql查询结果保留两位小数,如何做?

如何在SQL Server 2008中放置子查询

在 Laravel 4 中转义原始 SQL 查询

如何在 hive 中转置/透视数据?