sql >> Databáze >  >> RDS >> Oracle

převést sql tabulku ve formě matice

To může být pro vás užitečné. Použil jsem CASE WHEN THEN END bloků k dosažení 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

AKTUALIZACE

Nenašel jsem způsob, jak to napsat do jediného dotazu. Po nějaké analýze jsem našel toto .

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;
/

Vytvořená funkce, která dynamicky vytváří SQL a vrátí SYS_REFCURSOR . To lze spustit v SQL*Plus nebo SQL Developer (s 'spustit jako skript'),

VAR RC REFCURSOR;
EXEC :RC := GETUSERS;
PRINT RC



  1. PostgreSQL:Všestranný INSERT

  2. Jaký je kanonický způsob, jak stáhnout záznam z databáze MySQL, který má nejmenší/největší pole?

  3. Jak přidat stránkování v php

  4. Oracle SQL Developer 21.4.2 a SQLcl 21.4.1 jsou nyní k dispozici