Nejprve musíte toto rozbalit. Můžeme to udělat takto...
SELECT name,
ARRAY[grade_poor, grade_fair, grade_good, grade_vgood]
FROM grades
name | array
-------+-----------
arun | {1,4,2,1}
neha | {3,2,1,4}
ram | {1,1,3,0}
radha | {0,3,1,4}
Pak potřebujeme indexovat do známek... Děláme to pomocí CROSS JOIN LATERAL
. Máme 4 řádky s polem 4. Chceme 4*4 řádky.
SELECT name, grades, gs1.x, grades[gs1.x] AS gradeqty
FROM (
SELECT name,
ARRAY[grade_poor, grade_fair, grade_good, grade_vgood]
FROM grades
) AS t(name, grades)
CROSS JOIN LATERAL generate_series(1,4) AS gs1(x)
ORDER BY name, x;
name | grades | x | gradeqty
-------+-----------+---+----------
arun | {1,4,2,1} | 1 | 1
arun | {1,4,2,1} | 2 | 4
arun | {1,4,2,1} | 3 | 2
arun | {1,4,2,1} | 4 | 1
neha | {3,2,1,4} | 1 | 3
neha | {3,2,1,4} | 2 | 2
neha | {3,2,1,4} | 3 | 1
neha | {3,2,1,4} | 4 | 4
radha | {0,3,1,4} | 1 | 0
radha | {0,3,1,4} | 2 | 3
radha | {0,3,1,4} | 3 | 1
radha | {0,3,1,4} | 4 | 4
ram | {1,1,3,0} | 1 | 1
ram | {1,1,3,0} | 2 | 1
ram | {1,1,3,0} | 3 | 3
ram | {1,1,3,0} | 4 | 0
(16 rows)
Nyní zbývá, že musíme CROSS JOIN LATERAL
znovu k reprodukci x (našeho stupně), přes gradeqty
SELECT name,
gs1.x
FROM (
SELECT name,
ARRAY[grade_poor, grade_fair, grade_good, grade_vgood]
FROM grades
) AS t(name, grades)
CROSS JOIN LATERAL generate_series(1,4) AS gs1(x)
CROSS JOIN LATERAL generate_series(1,grades[gs1.x]) AS gs2(x)
ORDER BY name, gs1.x;
name | x
-------+---
arun | 1
arun | 2
arun | 2
arun | 2
arun | 2
arun | 3
arun | 3
arun | 4
neha | 1
neha | 1
neha | 1
neha | 2
neha | 2
neha | 3
neha | 4
neha | 4
neha | 4
neha | 4
radha | 2
radha | 2
radha | 2
radha | 3
radha | 4
radha | 4
radha | 4
radha | 4
ram | 1
ram | 2
ram | 3
ram | 3
ram | 3
(31 rows)
Nyní GROUP BY name
a pak použijeme Ordered-Set Aggregate Functions percent_disc
dokončit práci..
SELECT name, percentile_disc(0.5) WITHIN GROUP (ORDER BY gs1.x)
FROM (
SELECT name,
ARRAY[grade_poor, grade_fair, grade_good, grade_vgood]
FROM grades
) AS t(name, grades)
CROSS JOIN LATERAL generate_series(1,4) AS gs1(x)
CROSS JOIN LATERAL generate_series(1,grades[gs1.x]) AS gs2(x)
GROUP BY name ORDER BY name;
name | percentile_disc
-------+-----------------
arun | 2
neha | 2
radha | 3
ram | 3
(4 rows)
Chcete do toho jít dále a udělat to hezké...
SELECT name, (ARRAY['Poor', 'Fair', 'Good', 'Very Good'])[percentile_disc(0.5) WITHIN GROUP (ORDER BY gs1.x)]
FROM (
SELECT name,
ARRAY[grade_poor, grade_fair, grade_good, grade_vgood]
FROM grades
) AS t(name, grades)
CROSS JOIN LATERAL generate_series(1,4) AS gs1(x)
CROSS JOIN LATERAL generate_series(1,grades[gs1.x]) AS gs2(x)
GROUP BY name
ORDER BY name;
name | array
-------+-------
arun | Fair
neha | Fair
radha | Good
ram | Good
(4 rows)
Pokud získáme nového uživatele, můžeme získat trochu rozmanitější výstup.
INSERT INTO grades (name,grade_poor,grade_fair,grade_good,grade_vgood)
VALUES ('Bob', 0,0,0,100);
name | array
-------+-----------
arun | Fair
Bob | Very Good
neha | Fair
radha | Good
ram | Good
(5 rows)