복붙노트

[SQL] PostgreSQL의 행으로 변환 열? 바꾸어 놓다?

SQL

PostgreSQL의 행으로 변환 열? 바꾸어 놓다?

나는 나에게 다음과 같은 출력을 제공하는 PostgreSQL의 기능 (또는 테이블)가 :

Sl.no    username    Designation    salary   etc..
 1        A           XYZ            10000    ...
 2        B           RTS            50000    ...
 3        C           QWE            20000    ...
 4        D           HGD            34343    ...

지금은 아래와 같이 출력을 원하는 :

Sl.no            1       2        3       4       ...
 Username        A       B        C       D       ...
 Designation     XYZ     RTS      QWE     HGD     ...
 Salary          10000   50000    20000   34343   ...

이걸 어떻게 할까?

해결법

  1. ==============================

    1.형태의 테이블에 내 대답을 내놓고 :

    형태의 테이블에 내 대답을 내놓고 :

    CREATE TABLE tbl (
       sl_no int
     , username text
     , designation text
     , salary int
    );
    

    새 열에서 각 행의 결과를 반환합니다. 이 같은 동적 반환 형식으로, 데이터베이스에 대한 단일 호출이 완전히 동적를 만들기 위해 거의 가능합니다. 두 단계 솔루션을 시연 :

    일반적으로, 이것은 테이블에 저장할 수있는 열의 최대 수에 의해 제한된다. 1600 개 이상의 행 (이하)와 테이블 그래서이 아닌 옵션을 선택합니다. 세부:

    SELECT 'SELECT *
    FROM   crosstab(
           ''SELECT unnest(''' || quote_literal(array_agg(attname))
                               || '''::text[]) AS col
                 , row_number() OVER ()
                 , unnest(ARRAY[' || string_agg(quote_ident(attname)
                                  || '::text', ',') || ']) AS val
            FROM   ' || attrelid::regclass || '
            ORDER  BY generate_series(1,' || count(*) || '), 2''
       ) t (col text, '
         || (SELECT string_agg('r'|| rn ||' text', ',')
             FROM (SELECT row_number() OVER () AS rn FROM tbl) t)
         || ')' AS sql
    FROM   pg_attribute
    WHERE  attrelid = 'tbl'::regclass
    AND    attnum > 0
    AND    NOT attisdropped
    GROUP  BY attrelid;

    단일 매개 변수와 함수에 랩 될 수 있습니다 ... 형태의 쿼리를 생성합니다 :

    SELECT *
    FROM   crosstab(
           'SELECT unnest(''{sl_no,username,designation,salary}''::text[]) AS col
                 , row_number() OVER ()
                 , unnest(ARRAY[sl_no::text,username::text,designation::text,salary::text]) AS val
            FROM   tbl
            ORDER  BY generate_series(1,4), 2'
       ) t (col text, r1 text,r2 text,r3 text,r4 text)
    

    원하는 결과를 생성합니다 :

    col         r1    r2      r3     r4
    -----------------------------------
    sl_no       1      2      3      4
    username    A      B      C      D
    designation XYZ    RTS    QWE    HGD
    salary      10000  50000  20000  34343
    
    SELECT 'SELECT unnest(''{sl_no, username, designation, salary}''::text[] AS col)
         , ' || string_agg('unnest('
                        || quote_literal(ARRAY[sl_no::text, username::text, designation::text, salary::text])
                        || '::text[]) AS row' || sl_no, E'\n     , ') AS sql
    FROM   tbl;
    

    형태의 쿼리를 생성합니다 :

    SELECT unnest('{sl_no, username, designation, salary}'::text[]) AS col
         , unnest('{10,Joe,Music,1234}'::text[]) AS row1
         , unnest('{11,Bob,Movie,2345}'::text[]) AS row2
         , unnest('{12,Dave,Theatre,2356}'::text[]) AS row3
         , unnest('{4,D,HGD,34343}'::text[]) AS row4
    

    같은 결과.

    당신이 할 수있는 경우이 사용합니다. 나머지를 친다.

    SELECT 'SELECT *
    FROM   crosstab(
           $ct$SELECT u.attnum, t.rn, u.val
            FROM  (SELECT row_number() OVER () AS rn, * FROM '
                                  || attrelid::regclass || ') t
                 , unnest(ARRAY[' || string_agg(quote_ident(attname)
                                  || '::text', ',') || '])
                     WITH ORDINALITY u(val, attnum)
            ORDER  BY 1, 2$ct$
       ) t (attnum bigint, '
         || (SELECT string_agg('r'|| rn ||' text', ', ')
             FROM  (SELECT row_number() OVER () AS rn FROM tbl) t)
         || ')' AS sql
    FROM   pg_attribute
    WHERE  attrelid = 'tbl'::regclass
    AND    attnum > 0
    AND    NOT attisdropped
    GROUP  BY attrelid;

    attnum 대신 실제 열 이름과 함께 작동. 간단하고 빠르게. 한 번 더 pg_attribute 또는 페이지 9.3의 예에서와 같이 열 이름을 통합하는 결과에 가입하세요. 형태의 쿼리를 생성합니다 :

    SELECT *
    FROM   crosstab(
           $ct$SELECT u.attnum, t.rn, u.val
            FROM  (SELECT row_number() OVER () AS rn, * FROM tbl) t
                 , unnest(ARRAY[sl_no::text,username::text,designation::text,salary::text])
                    WITH ORDINALITY u(val, attnum)
            ORDER  BY 1, 2$ct$
       ) t (attnum bigint, r1 text, r2 text, r3 text, r4 text);
    

    이 고급 기능의 전체 범위를 사용합니다. 그냥 너무 많은 설명합니다.

    하나 unnest은 ()가 병렬로 unnest 여러 배열을 취할 수 있습니다.

    SELECT 'SELECT * FROM unnest(
      ''{sl_no, username, designation, salary}''::text[]
    , ' || string_agg(quote_literal(ARRAY[sl_no::text, username::text, designation::text, salary::text])
                  || '::text[]', E'\n, ')
        || E') \n AS t(col,' || string_agg('row' || sl_no, ',') || ')' AS sql
    FROM   tbl;
    

    결과:

    SELECT * FROM unnest(
     '{sl_no, username, designation, salary}'::text[]
    ,'{10,Joe,Music,1234}'::text[]
    ,'{11,Bob,Movie,2345}'::text[]
    ,'{12,Dave,Theatre,2356}'::text[])
     AS t(col,row1,row2,row3,row4)
    

    SQL 바이올린은 페이지 9.3에서 실행.

  2. ==============================

    2.

    SELECT
       unnest(array['Sl.no', 'username', 'Designation','salary']) AS "Columns",
       unnest(array[Sl.no, username, value3Count,salary]) AS "Values"
    FROM view_name
    ORDER BY "Columns"
    

    참조 : convertingColumnsToRows

  3. ==============================

    3.당신이 bash는 스크립트에서이 정보를 필요로했다 (나 같은) 경우, 노트는 행으로 출력 테이블 컬럼에 말할 수 psql를위한 간단한 명령 줄 스위치가 있습니다 :

    당신이 bash는 스크립트에서이 정보를 필요로했다 (나 같은) 경우, 노트는 행으로 출력 테이블 컬럼에 말할 수 psql를위한 간단한 명령 줄 스위치가 있습니다 :

    psql mydbname -x -A -F= -c "SELECT * FROM foo WHERE id=123"
    

    -x 옵션은 행으로 출력 컬럼에 psql의를 얻는 열쇠입니다.

  4. ==============================

    4.나는 어윈보다 단순한 접근 방식은 포스트 그레스와 함께 나를 위해, 위의 그 노동자 지적이 (그리고 나는 그것이 누구의 지원 SQL 표준 모든 주요 관계형 데이터베이스 작업을해야한다고 생각)

    나는 어윈보다 단순한 접근 방식은 포스트 그레스와 함께 나를 위해, 위의 그 노동자 지적이 (그리고 나는 그것이 누구의 지원 SQL 표준 모든 주요 관계형 데이터베이스 작업을해야한다고 생각)

    당신은 크로스 탭 대신 단순히 UNION을 사용할 수 있습니다 :

    SELECT text 'a' AS "text" UNION SELECT 'b';
    
     text
    ------
     a
     b
    (2 rows)
    

    물론이 적용하려고하는 경우에 따라 달라집니다. 당신은 당신이 필요로하는 필드 것을 사전에 알고있는 점을 감안하면, 당신도 다른 테이블을 조회하는이 방법을 취할 수 있습니다. 즉 :

    SELECT 'My first metric' as name, count(*) as total from first_table UNION
    SELECT 'My second metric' as name, count(*) as total from second_table 
    
     name             | Total
    ------------------|--------
     My first metric  |     10
     My second metric |     20
    (2 rows)
    

    그것은 IMHO, 더 유지 보수 방법입니다. 자세한 내용은이 페이지를 봐 : https://www.postgresql.org/docs/current/typeconv-union-case.html

  5. ==============================

    5.일반 SQL 또는 PL / pgSQL의에서이 작업을 수행 할 적절한 방법이 없습니다.

    일반 SQL 또는 PL / pgSQL의에서이 작업을 수행 할 적절한 방법이 없습니다.

    그것은 DB에서 데이터를 얻는 응용 프로그램에서이 작업을 수행하기 위해 더 나은 방법이 될 것입니다.

  6. from https://stackoverflow.com/questions/14084503/postgresql-convert-columns-to-rows-transpose by cc-by-sa and MIT license