Reputation: 5857
The real problem is probably less complex than the subject might suggest.
The schema
Three tables (simplified). There can be multiple people within one membership. The main member is identified as 1
in person_membership.relationship
, there can be a spouse of the main member identified as '2' and other dependants (any other number).
CREATE TABLE person
([first_name] varchar(10), [surname] varchar(10), [date_of_birth] date, [person_id] int);
INSERT INTO person
([first_name], [surname], [date_of_birth] ,[person_id])
VALUES
('Alice', 'AA', '1/1/1990', 1),
('Bob' , 'AA', '1/1/1990', 2),
('Carol', 'AA', '1/1/1990', 3),
('Dave' , 'AA', '1/1/1990', 4),
('Elen' , 'AA', '1/1/1990', 5),
('Fran' , 'BB', '1/1/1990', 6),
('Gaby' , 'BB', '1/1/1990', 7)
CREATE TABLE person_membership
([person_id] int, [status_flag] varchar(1), [membership_id] int, [relationship] int);
INSERT INTO person_membership
([person_id], [status_flag], [membership_id], [relationship])
VALUES
(1, 'A', 10, 1),
(2, 'A', 10, 2),
(3, 'A', 10, 3),
(4, 'A', 10, 4),
(5, 'A', 10, 4),
(6, 'A', 20, 1),
(7, 'A', 20, 3);
CREATE TABLE memship
([membership_id] int, [memship_status] varchar(1));
INSERT INTO memship
([membership_id], [memship_status])
VALUES
(10, 'A'),
(20, 'A');
The task
Simplified version - display membership and person id of the main member and identify if they have a spouse, and also if they have any dependants show how many of them they are.
The desired output
The basic version something like the screenshot below. Main member ID, their person ID, Yes/No field for spouse, number of dependants:
The current solution
The code below works and creates the desired output but it seems very clunky. There must be more elegant ways of doing it?
WITH peeps AS (SELECT person.person_id,
person.first_name,
person.surname,
person_membership.membership_id,
person_membership.relationship
FROM memship, person, person_membership
WHERE person_membership.person_id = person.person_id
AND memship.membership_id = person_membership.membership_id
AND person_membership.status_flag='A'
AND memship.memship_status='A')
SELECT final.MemID, final.PersonID, sum(final.Spouse) as 'Spouse?', sum(final.Kids) as 'No of kids'
FROM (
SELECT
peeps1.membership_id AS 'MemID',
CASE peeps1.relationship
WHEN 1 THEN peeps1.person_id
ELSE peeps2.person_id
END AS 'PersonID',
SUM (CASE WHEN
peeps1.relationship = 2 THEN 1
ELSE 0
END ) AS 'Spouse',
SUM (CASE WHEN
peeps1.relationship > 2 THEN 1
ELSE 0
END ) AS 'Kids'
FROM peeps peeps1
INNER JOIN peeps peeps2 ON peeps2.membership_id = peeps1.membership_id AND peeps2.relationship = 1
GROUP BY peeps1.membership_id, peeps1.relationship, peeps1.person_id, peeps2.person_id) as final
GROUP BY final.MemID, final.PersonID
Upvotes: 2
Views: 324
Reputation:
SELECT M.membership_id,
MAX(CASE WHEN PM.relationship = 1 THEN P.person_id ELSE NULL END) person_id,
COUNT(CASE WHEN PM.relationship = 2 THEN 1 ELSE 0 END )AS 'Spouse',
COUNT(CASE WHEN PM.relationship IN (3, 4, 5) THEN 1 ELSE 0 END ) AS 'Kids'
FROM memship M
JOIN person_membership PM ON M.membership_id = PM.membership_id
JOIN person P ON PM.person_id = P.person_id
WHERE PM.status_flag='A' AND M.memship_status='A'
GROUP BY M.membership_id
Upvotes: 1
Reputation: 28403
Try This
SELECT M.membership_id,
MAX(CASE WHEN PM.relationship = 1 THEN P.person_id ELSE NULL END) person_id,
SUM (CASE WHEN PM.relationship = 2 THEN 1 ELSE 0 END )AS 'Spouse',
SUM (CASE WHEN PM.relationship > 2 THEN 1 ELSE 0 END ) AS 'Kids'
FROM memship M
JOIN person_membership PM ON M.membership_id = PM.membership_id
JOIN person P ON PM.person_id = P.person_id
WHERE PM.status_flag='A' AND M.memship_status='A'
GROUP BY M.membership_id
Upvotes: 2
Reputation: 24763
Simplified query
SELECT MemID = pm.membership_id,
PersonID = MAX (CASE WHEN pm.relationship = 1 THEN p.person_id END),
[Spouce?] = SUM (CASE WHEN pm.relationship = 2 THEN 1 ELSE 0 END),
[No of kids] = SUM (CASE WHEN pm.relationship NOT IN (1, 2) THEN 1 ELSE 0 END)
FROM person p
INNER JOIN person_membership pm ON p.person_id = pm.person_id
INNER JOIN memship m ON pm.membership_id = m.membership_id
WHERE pm.status_flag = 'A'
AND m.memship_status = 'A'
GROUP BY pm.membership_id
Note : please avoid using old style of join. User INNER JOIN
instead
Upvotes: 1