简体   繁体   English

如何从分组行中提取值到 Oracle SQL 中的特定列?

[英]How to extract values from grouped rows to specific columns in Oracle SQL?

Suppose I have a table like this in Oracle:假设我在 Oracle 中有这样的表:

+----------+-----------+--------+
| PersonId | ValueType | Value  |
+----------+-----------+--------+
|        1 | FirstName | John   |
|        1 | LastName  | Smith  |
|        2 | FirstName | John   |
|        2 | LastName  | Doe    |
|        2 | City      | London |
+----------+-----------+--------+

How can I select the data like the following:我怎样才能 select 数据如下:

+----------+-----------+----------+--------+
| PersonId | FirstName | LastName |  City  |
+----------+-----------+----------+--------+
|        1 | John      | Smith    |        |
|        2 | John      | Doe      | London |
+----------+-----------+----------+--------+

? ?

Try with case expressions to pivot your data.尝试使用case表达式对您的数据进行 pivot。

select
    PersonId,
    max(case when ValueType = 'FirstName' then Value end) as FirstName,
    max(case when ValueType = 'LastName' then Value end) as LastName,
    max(case when valueType = 'City' then value end) City
from yourTable
group by
    PersonId

You can pivot your dataset with conditional aggregation:您可以使用条件聚合 pivot 您的数据集:

select
    personid,
    max(case when valuetype = 'FirstName' then value end) firstname,
    max(case when valuetype = 'LastName'  then value end) lastname,
    max(case when valuetype = 'City'      then value end) city
from mytable
group by personid

The old way of pivoting (and, importantly, the SQL Standard compliant way) uses conditional aggregation, as shown in zealous's and GMB's answers.旧的旋转方式(重要的是,符合 SQL 标准的方式)使用条件聚合,如 zealous 和 GMB 的答案所示。

Oracle introduced the pivot (and related unpivot ) operator in version 11.1, that is, a very long time ago. Oracle 在很久以前的 11.1 版本中引入了pivot (以及相关的unpivot )算子。 I illustrate that approach below.我在下面说明了这种方法。 These operators are particularly helpful when we need to pivot (or unpivot) multiple columns at a time;当我们需要一次 pivot(或反透视)多个列时,这些运算符特别有用; however, that's not the case in this thread.但是,在这个线程中情况并非如此。

Setting up the test table:设置测试表:

create table person (personid, valuetype, value) as
  select 1, 'FirstName', 'John'   from dual union all 
  select 1, 'LastName' , 'Smith'  from dual union all
  select 2, 'FirstName', 'John'   from dual union all
  select 2, 'LastName' , 'Doe'    from dual union all
  select 2, 'City'     , 'London' from dual
;

Query and output:查询和output:

select personid, firstname, lastname, city
from   person
pivot  (min(value) for valuetype in ( 'FirstName' as firstname
                                    , 'LastName'  as lastname
                                    , 'City'      as city
                                    )
       )
;

PERSONID FIRSTNAME LASTNAME  CITY  
-------- --------- --------- ------
       1 John      Smith        
       2 John      Doe       London

And - perhaps more as a curiosity (with more serious applicability, maybe, to other, harder problems) - here is a solution using match_recognize , introduced in Oracle 12.1.而且-也许更多是出于好奇(可能对其他更难的问题具有更严重的适用性)-这是使用match_recognize的解决方案,在 Oracle 12.1 中引入。 Importantly, unlike any other solutions, this approach does not use aggregation of any kind.重要的是,与任何其他解决方案不同,这种方法不使用任何类型的聚合。

select personid, firstname, lastname, city
from   person
match_recognize
  (
    partition by personid
    measures  f.value as firstname
           ,  l.value as lastname
           ,  c.value as city
    pattern   ( (f|l|c)* )
    define    f as valuetype = 'FirstName'
         ,    l as valuetype = 'LastName'
         ,    c as valuetype = 'City'
  )
;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM