2

I need to transpose columns to rows in postgres, below is the requirement. Any help is appreciated.

Source table/data :

id   class-1-male class-1-female class-2-male  class-2-female class-3-male  class-3-female 
1      1                1                11              7          0                9
2      11              31                6              7          40               92
3      15              31                8              37         30               91
4      11              13                50             17         10               19

I want data in below format:

id   class-type male female
1     class-1    1     1
2     class-1    11    31
3     class-1    15    31
4     class-1    11    13
1     class-2    11    7
2     class-2    6     7
3     class-2    8     37
4     class-2    50    17
1     class-3    0     9
2     class-3    40    92
3     class-3    30    91
4     class-3    10    19
2

1 Answer 1

3

If you wanted to do the opposite (which is really more common) you could use hte tablefunc contrib module. But this way, you can simply use UNION ALL and query each column separately:

SELECT id, 'class-1' AS class-type,
       class-1-male AS male, class-1-female AS female
FROM your_table
UNION ALL
SELECT id, 'class-2' AS class-type,
       class-2-male AS male, class-2-female AS female
FROM your_table
UNION ALL
SELECT id, 'class-3' AS class-type,
       class-3-male AS male, class-3-female AS female
FROM your_table

If you have too many rows on this table, this may not be the best option, because it reads the entire dataset for each query, which means it read them all three times when it could read just once. Another option would be creating a function that returns the set:

CREATE OR REPLACE FUNCTION classes_transpose()
RETURNS TABLE(id int, class_type text, male int, female int)
LANGUAGE PLPGSQL
STABLE
AS $$
DECLARE
    v RECORD;
BEGIN
    FOR v IN SELECT * FROM your_table LOOP
        id := v.id;
        class_type := 'class-1';
        male := v."class-1-male";
        female := v."class-1-female";
        RETURN NEXT;
        class_type := 'class-2';
        male := v."class-2-male";
        female := v."class-2-female";
        RETURN NEXT;
        class_type := 'class-3';
        male := v."class-3-male";
        female := v."class-3-female";
        RETURN NEXT;
    END LOOP;
END;
$$;

Then:

SELECT * FROM classes_transpose();
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.