I have a table that stores two foreign keys, implementing a n:m relationship.
One of them points to a person (subject
), the other one to a specific item.
Could work like this (pure SQL solution):
SELECT a.sal_subject
, b.sub_item
FROM (
SELECT generate_series(1, max_items) AS rn
, sal_subject
FROM subject
) a
LEFT JOIN (
SELECT row_number() OVER (PARTITION BY sal_subject ORDER BY sub_item) AS rn
, sal_subject
, sub_item
FROM subject_items
) b USING (sal_subject, rn)
ORDER BY sal_subject, rn
LEFT JOIN
the existing items to the theoretical items per subject. Missing items are filled in with NULL.In addition to the table you disclosed in the question, I assume a column that holds the maximum number of items in the subject
table:
CREATE temp TABLE subject
( sal_subject integer, -- primary key of subject
max_items int); -- max. number of items
Query for PostgreSQL 8.3, substituting for the missing window function row_number()
:
SELECT a.sal_subject
, b.sub_item
FROM (
SELECT generate_series(1, max_items) AS rn
, sal_subject
FROM subject
) a
LEFT JOIN (
SELECT rn, sal_subject, arr[rn] AS sub_item
FROM (
SELECT generate_series(1, ct) rn, sal_subject, arr
FROM (
SELECT s.sal_subject
, s.ct
, ARRAY(
SELECT sub_item
FROM subject_items s0
WHERE s0.sal_subject = s.sal_subject
ORDER BY sub_item
) AS arr
FROM (
SELECT sal_subject
, count(*) AS ct
FROM subject_items
GROUP BY 1
) s
) x
) y
) b USING (sal_subject, rn)
ORDER BY sal_subject, rn
More about substituting row_number()
in this article by Quassnoi.