SQL Server - выберите и объедините родительско-дочерние записи, сводку и группу - PullRequest
2 голосов
/ 08 ноября 2019

Реальная проблема, вероятно, менее сложна, чем можно предположить.

Схема

Три таблицы (упрощенно). В одном членстве может быть несколько человек. Основной член обозначен как 1 в person_membership.relationship, может быть супруга основного члена, обозначенная как «2», и другие иждивенцы (любое другое число).

  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');

task

Упрощенная версия - отобразить членство и идентификатор лица основного члена и определить, есть ли у них супруг (а), а также, есть ли у них иждивенцы, показать, сколько из них они.

Требуемый вывод

Базовая версия, что-то вроде скриншота ниже. Идентификатор основного члена, его личность, поле Да / Нет для супруга, количество иждивенцев: enter image description here

Текущее решение

Theприведенный ниже код работает и создает желаемый результат, но кажется очень неуклюжим. Должны ли быть более элегантные способы сделать это?

    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

Ответы [ 3 ]

2 голосов
/ 08 ноября 2019

Попробуйте

FIDDLE DEMO

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
2 голосов
/ 08 ноября 2019
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
1 голос
/ 08 ноября 2019

Упрощенный запрос

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

Примечание: пожалуйста, не используйте старый стиль соединения. Пользователь INNER JOIN вместо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...