Not*_*tMe 22 oracle oracle-11g pivot linked-server
我有一个 SQL Server 实例,它具有到 Oracle 服务器的链接服务器。Oracle 服务器上有一个名为的表,PersonOptions其中包含以下数据:
???????????????????????
? PersonID ? OptionID ?
???????????????????????
? 1 ? A ?
? 1 ? B ?
? 2 ? C ?
? 3 ? B ?
? 4 ? A ?
? 4 ? C ?
???????????????????????
Run Code Online (Sandbox Code Playgroud)
我需要对这些数据进行透视,因此结果是:
????????????????????????????????????????????
? PersonID ? OptionA ? Option B ? Option C ?
????????????????????????????????????????????
? 1 ? 1 ? 1 ? ?
? 2 ? ? ? 1 ?
? 3 ? ? 1 ? ?
? 4 ? 1 ? ? 1 ?
????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)
有什么建议?
Tar*_*ryn 22
有几种方法可以执行此数据转换。您可以访问该PIVOT函数,那么这将是最简单的,但如果没有,那么您可以使用聚合函数和CASE.
聚合/案例版本:
select personid,
max(case when optionid = 'A' then 1 else 0 end) OptionA,
max(case when optionid = 'B' then 1 else 0 end) OptionB,
max(case when optionid = 'C' then 1 else 0 end) OptionC
from PersonOptions
group by personid
order by personid;
Run Code Online (Sandbox Code Playgroud)
静态枢轴:
select *
from
(
select personid, optionid
from PersonOptions
) src
pivot
(
count(optionid)
for optionid in ('A' as OptionA, 'B' OptionB, 'C' OptionC)
) piv
order by personid
Run Code Online (Sandbox Code Playgroud)
动态版本:
如果您有已知数量的值,则上述两个版本效果很好,但如果您的值未知,那么您将需要实现动态 sql 并且在 Oracle 中您可以使用一个过程:
CREATE OR REPLACE procedure dynamic_pivot_po(p_cursor in out sys_refcursor)
as
sql_query varchar2(1000) := 'select personid ';
begin
for x in (select distinct OptionID from PersonOptions order by 1)
loop
sql_query := sql_query ||
' , min(case when OptionID = '''||x.OptionID||''' then 1 else null end) as Option_'||x.OptionID;
dbms_output.put_line(sql_query);
end loop;
sql_query := sql_query || ' from PersonOptions group by personid order by personid';
dbms_output.put_line(sql_query);
open p_cursor for sql_query;
end;
/
Run Code Online (Sandbox Code Playgroud)
然后你返回结果,你将使用:
variable x refcursor
exec dynamic_pivot_po(:x)
print x
Run Code Online (Sandbox Code Playgroud)
所有版本的结果都相同:
| PERSONID | OPTIONA | OPTIONB | OPTIONC |
------------------------------------------
| 1 | 1 | 1 | 0 |
| 2 | 0 | 0 | 1 |
| 3 | 0 | 1 | 0 |
| 4 | 1 | 0 | 1 |
Run Code Online (Sandbox Code Playgroud)
bil*_*nkc 10
这在 SQL Server 语法中是等效的。根据我对 Oracle 文档的阅读,NULLIF和PIVOT似乎与它们的 SQL Server 亲属具有相同的格式。挑战将是需要静态的数据透视表,除非您像 Itzik演示的那样使查询动态化,但我不知道是否可以将其转换为 P/SQL
WITH PersonOptions(PersonID, OptionId) AS
(
SELECT 1, 'A'
UNION ALL SELECT 1, 'B'
UNION ALL SELECT 2, 'C'
UNION ALL SELECT 3, 'B'
UNION ALL SELECT 4, 'A'
UNION ALL SELECT 4, 'C'
)
SELECT
P.PersonId
, NULLIF(P.A, 0) AS OptionA
, NULLIF(P.B, 0) AS OptionB
, NULLIF(P.C, 0) AS OptionC
FROM
PersonOptions PO
PIVOT
(
COUNT(PO.OptionId)
FOR OPtionId IN (A, B, C)
) P;
Run Code Online (Sandbox Code Playgroud)
我更喜欢手动透视查询,但您也可以使用PIVOT。
SELECT PersonID,
MAX(CASE WHEN OptionId ='A' THEN 1 END) AS OptionA,
MAX(CASE WHEN OptionId ='B' THEN 1 END) AS OptionB,
MAX(CASE WHEN OptionId ='C' THEN 1 END) AS OptionC
FROM PersonOptions
GROUP BY PersonID
Run Code Online (Sandbox Code Playgroud)