基于列获取单行中的合并行的SQL

基于列获取单行中的合并行的SQL,sql,oracle,Sql,Oracle,我有一张桌子如下: +---+---+---+ |obj|col|Val| +---+---+---+ |1 |c1 | v1| +---+---+---+ |1 |c2 | v2| +---+---+---+ |2 |c1 | v3| +---+---+---+ |2 |c2 | v4| +---+---+---+ 我正在寻找SQL,它将以以下格式给出结果 +---+---+---+ |obj|c1 |c2 | +---+---+---+ |1 |v1 | v2| +---+---

我有一张桌子如下:

+---+---+---+
|obj|col|Val|
+---+---+---+
|1  |c1 | v1|
+---+---+---+
|1  |c2 | v2|
+---+---+---+
|2  |c1 | v3|
+---+---+---+
|2  |c2 | v4|
+---+---+---+
我正在寻找SQL,它将以以下格式给出结果

+---+---+---+
|obj|c1 |c2 |
+---+---+---+
|1  |v1 | v2|
+---+---+---+
|2  |v3 | v4|
+---+---+---+

在这个SQL中,我检查col='c',并打印出相应的Val。但是使用group by的原因是为了在条件不匹配的情况下避免所有空值。通过在obj上分组,将避免所有空值,并产生所需的结果

SELECT obj,
       MAX( CASE WHEN col = 'c1' THEN Val END ) AS c1,
       MAX( CASE WHEN col = 'c2' THEN Val END ) AS c2
  FROM Table
 GROUP BY obj;

首先,需要从表中选择所有唯一id

select distinct id
from a_table_you_did_not_name
如何使用它左键连接到列

select base.id, one.val as c1, two.val as c2
from (
  select distinct id
  from a_table_you_did_not_name
) base
left join a_table_you_did_not_name one on one.id = base.id and one.col = 'c1'
left join a_table_you_did_not_name two on two.id = base.id and two.col = 'c2'
注意:您的案例是这种连接的一个相对简单的案例——我这样编码,因为使用我的方法可以扩展到更复杂的案例,并且仍然有效。对于这个特定的需求,还有其他一些方法可能更简单

具体来说,最常见的是连接到多个表,而不是所有表都在同一个表中。我的方法在这些情况下仍然有效


在SQL和Oracle中,这绝对不是数据透视的方式。另一个标有“正确”的答案显示了最普遍的解决方案。在Oracle11及更高版本中,还有PIVOT子句。数据透视不需要连接。@mathguy-这样做和使用PIVOT子句之间没有内在区别。另一个答案不是最一般的解决方案,考虑有两个表的情况,并希望得到5列的结果。我的延伸到了那个案例,而Teja的没有。我不确定你们所说的内部差异是什么意思,我不熟悉这个概念。但不同之处在于,您的解决方案将基表读取三次,而不是使用标准PIVOT解决方案仅读取一次。你否认吗?因此,您需要进行大量不必要且昂贵的I/O。另一种解决方案是最通用的数据透视解决方案。你的解决方案不是旋转;从你所说的意义上讲,它更一般,但是这解决了OP在这个线程中没有的一个问题。是的,我否认这一点-我相信如果你有两个表,pivot查询的工作原理是完全相同的,这是我在黄色注释中说的更常见的情况。对于这个特殊的要求,还有一些其他的方法可能更简单。还要记住,在许多情况下,GROUP BY的性能比索引联接糟糕,例如大型和稀疏连接。分组需要大量内存和处理。你没有领会我的意思。PIVOT只读取一次表,您的联接读取三次表。你说你在否认这一点,如果你是的话,你可以自己检查一下执行计划,但你给出的理由与此无关。