【问题标题】:rows as columns sql行作为列 sql
【发布时间】:2013-03-20 13:45:12
【问题描述】:

我有两张这样的桌子

表 1

profile
--------
id
---
1 | XXX
2 | zzz

表 2

profile_details
-----------------
id |    K       |   V
---------------------------
1  | first_name | XXX
1  | last_name  | YYY
1  | gender     | female
2  | name       | zzzzz
2  | gender     | male
2  | phone      | 8999xxxx
2  | location   | india
2  | spoken_language | hindi

我使用这个查询来获取作为列的行

select profiles.id,
max( decode( k, 'first_name', v, NULL )) first_name,
max(decode(k, 'last_name', v, null))as last_name ,
max( decode( k, 'gender', v, NULL)) gender
from profile_details , profiles
where 
profile_details.id = profiles.id 
and
profile_details.id=1
group by profiles.id

找我

id | first_name| last_name | gender
--------------------------------------------
1  |   XXX     |  YYY      | female

这可以将行作为列获取。但是如何更改此查询以动态包含列,因为 K 值可以是任何可能的值。

例如,对于 id 2,它应该是

id | name | gender | mobile   |   location  | spoken_language
------------------------------------------------------------------
2  | zzz  | male   | 8999xxxx |   india     | hindi

谢谢 V

【问题讨论】:

  • 您的问题的简单答案是“否”。 SQL 语句必须显式列出要返回的列。扩展的答案是:你了解动态 SQL 吗?

标签: sql oracle11g pivot


【解决方案1】:

这里有一个实体-属性-值模式,通常用于提供模式的灵活性。

不利的一面是,从现在开始,您所做的一切都将是难以言喻的痛苦和困难,包括这个,没有简单的解决方案。

这是一个关于这个主题的课程:https://www.simple-talk.com/opinion/opinion-pieces/bad-carma/

【讨论】:

    【解决方案2】:

    您可以使用动态 SQL 来生成要执行的字符串。

    在 Oracle 中,我将使用一个过程,我可以传入必要的 id 值,然后返回 sys_refcursor

    该过程类似于以下内容:

    CREATE OR REPLACE procedure dynamic_pivot_profile(p_cursor in out sys_refcursor, p_id in number)
    as
        sql_query varchar2(1000) := 'select p.id ';
    
        begin
            for x in (select distinct k from profile_details where id=p_id order by 1)
            loop
                sql_query := sql_query ||
                    ' , max(case when pd.k = '''||x.k||''' then pd.v end) as "'||x.k||'"';
    
                    dbms_output.put_line(sql_query);
            end loop;
    
            sql_query := sql_query || ' from profile p 
                                                    inner join profile_details pd
                                                      on P.ID = pd.id
                                                    where PD.ID = '||p_id||'
                                                    group by p.id';
            dbms_output.put_line(sql_query);
    
            open p_cursor for sql_query;
        end;
    /
    

    然后你返回结果,我在TOAD中使用如下:

    variable x refcursor
    exec dynamic_pivot_profile(:x, 1) -- pass in your id
    print x
    

    这将返回您提供的所需结果。

    【讨论】:

    • 如果数据量很大,这个查询的性能如何?
    • @user1353364 每当您尝试转换大量数据时,都可能会遇到性能问题。这就是为什么这种类型的数据表示应该在应用程序的表示层而不是 SQL 代码中完成的部分原因。此外,您还需要确保表上有适当的索引。
    猜你喜欢
    • 2017-12-16
    • 2021-09-22
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多