我在oracle中有一个表,我想以矩阵形式转换它
表1:我有两种具有相应权重的用户
User_name M_User Total
user 1 user 2 7
user 1 user 3 19
user 1 user 7 5
user 3 user 2 1
user 2 user 7 1
最终结果应该是这样的:用户1 - >用户2的权重为7,因此该值出现在该单元格中,依此类推
user 1 user 2 user 3 user 7
user 1 0 7 19 5
user 3 0 1 0 0
user 2 0 0 0 1
user 7 0 0 0 0
经过一番研究后,我找到了Pivot功能并使用了它。
SELECT *
FROM (SELECT USER_NAME, M_USER, TOTAL
FROM TEST)
PIVOT (MAX(TOTAL) FOR (M_USER) IN ('user 2' AS User2, 'user 3' AS User3 , 'user7' AS User7))
第一个问题是它显示用户7'的空值。并且它不应该,第二个问题是我的文件中有很多数据(107k记录,包括重复数据),对于有限的数据,如上所述我可以在'user 2' AS User2, 'user 3' AS User3 , 'user7' AS User7
命令之后使用IN
这么大的数据怎么写这行?当然,我不能在IN
更新: 在sql developer中运行命令为"运行脚本"
Error starting at line 2 in command:
EXEC :rc := getusers;
Error report:
ORA-06550: line 1, column 13:
PLS-00905: object SYSTEM.GETUSERS is invalid
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
rc
答案 0 :(得分:2)
这可能对您有所帮助。我使用CASE WHEN THEN END
块来实现PIVOT
。
SELECT USERS.USER_NAME
, MAX(COALESCE(TEST.USER1, 0)) USER1
, MAX(COALESCE(TEST.USER2, 0)) USER2
, MAX(COALESCE(TEST.USER3, 0)) USER3
, MAX(COALESCE(TEST.USER7, 0)) USER7
FROM (
SELECT DISTINCT USER_NAME
FROM (
SELECT USER_NAME FROM TEST
UNION ALL
SELECT M_USER FROM TEST
)
) USERS
LEFT OUTER JOIN (
SELECT
USER_NAME
, M_USER
, CASE WHEN M_USER = 'user 1' THEN TOTAL ELSE 0 END AS USER1
, CASE WHEN M_USER = 'user 2' THEN TOTAL ELSE 0 END AS USER2
, CASE WHEN M_USER = 'user 3' THEN TOTAL ELSE 0 END AS USER3
, CASE WHEN M_USER = 'user 7' THEN TOTAL ELSE 0 END AS USER7
FROM TEST
) TEST ON USERS.USER_NAME = TEST.USER_NAME
GROUP BY USERS.USER_NAME
ORDER BY USERS.USER_NAME
<强>更新强>
我找不到在单个查询中写这个的方法。经过一些分析后,我找到了this。
CREATE OR REPLACE FUNCTION GETUSERS RETURN SYS_REFCURSOR AS
QUERY VARCHAR2(32767);
RC SYS_REFCURSOR;
BEGIN
QUERY := 'SELECT USERS.USER_NAME ';
FOR TMP IN (SELECT DISTINCT UPPER(REPLACE(USER_NAME, ' ', '')) USER_NAME FROM (SELECT USER_NAME FROM TEST UNION ALL SELECT M_USER FROM TEST) ORDER BY USER_NAME)
LOOP
QUERY := QUERY || ' , MAX(COALESCE(TEST.' || TMP.USER_NAME || ' , 0)) ' || TMP.USER_NAME;
END LOOP;
QUERY := QUERY || ' FROM ( ';
QUERY := QUERY || ' SELECT DISTINCT USER_NAME ';
QUERY := QUERY || ' FROM ( ';
QUERY := QUERY || ' SELECT USER_NAME FROM TEST ';
QUERY := QUERY || ' UNION ALL ';
QUERY := QUERY || ' SELECT M_USER FROM TEST ';
QUERY := QUERY || ' ) ';
QUERY := QUERY || ' ) USERS ';
QUERY := QUERY || ' LEFT OUTER JOIN ( ';
QUERY := QUERY || ' SELECT USER_NAME';
FOR TMP IN (SELECT DISTINCT USER_NAME, REPLACE(USER_NAME, ' ', '') USER_COL_NM FROM (SELECT USER_NAME FROM TEST UNION ALL SELECT M_USER FROM TEST))
LOOP
QUERY := QUERY || ', CASE WHEN M_USER = ''' || TMP.USER_NAME
|| ''' THEN TOTAL ELSE 0 END AS ' || TMP.USER_COL_NM ;
END LOOP;
QUERY := QUERY || ' FROM TEST';
QUERY := QUERY || ' ) TEST ON USERS.USER_NAME = TEST.USER_NAME ';
QUERY := QUERY || 'GROUP BY USERS.USER_NAME ';
QUERY := QUERY || 'ORDER BY USERS.USER_NAME';
OPEN RC FOR QUERY;
RETURN RC;
END;
/
创建的函数,动态创建SQL
并返回SYS_REFCURSOR
。这可以在SQL * Plus或SQL Developer中运行(使用&#39;作为脚本运行&#39;),
VAR RC REFCURSOR;
EXEC :RC := GETUSERS;
PRINT RC