Выбор людей в таблице и исключение жены, но объединить их имена

У меня есть таблица Person:

PersonID | FirstName | LastName
-------------------------------
1        |   John    |  Doe
2        |   Jane    |  Doe
3        |  NoSpouse | Morales
4        | Jonathan  | Brand
5        | Shiela    | Wife

И таблица Relationship:

RelationshipID | PersonID | Type | RelatedPersonID
1              |    1     |  3   |     2
2              |    2     |  3   |     1
3              |    4     |  3   |     5
4              |    5     |  3   |     4

В принципе, я хочу совместить имена супруга и клиента, но я хочу исключить супруга:

Ожидаемые результаты:

1,  John and Jane Doe, 2
----------------------
3, NoSpouse Morales, null
-----------------------
4, Jonathan and Shiela Brand, 5

Я пробовал:

SELECT p.PersonID,
    Case when spouse.PersonID is not null 
        THEN p.FirstName + ' and ' + spouse.FirstName + ' ' + p.LastName
    ELSE p.FirstName + ' ' + p.LastName END as ClientName,
    spouse.PersonID as RelatedPersonID
FROM Person p
LEFT JOIN Relationship r on p.PersonID = r.PersonID
LEFT JOIN Person spouse on r.RelatedPersonID = spouse.PersonID
WHERE r.Type = 3 OR spouse.PersonID is null

но результаты:

1,  John and Jane Doe, 2
----------------------
2,  Jane and John Doe, 1
----------------------
3, NoSpouse Morales, null
-----------------------
4, Jonathan and Shiela Brand, 5
-------------------------------
5, Shiela and Jonathan Wife, 4

Вот некоторые из них:

create table Person(
    PersonID int primary key,
    FirstName varchar(max),
    LastName varchar(max)
)
insert into Person values 
(1, 'John', 'Doe'), 
(2, 'Jane', 'Doe'), 
(3, 'NoSpouse', 'Morales'), 
(4, 'Jonathan', 'Brand'), 
(5,'Shiela','Wife')

create table Relationship (
    RelationshipID int,
    PersonID int references Person(PersonID),
    Type int,
    RelatedPersonID int references Person(PersonID)
)
insert into Relationship values 
(1, 1, 3, 2),
(2, 2, 3, 1),
(3, 4, 3, 5),
(4, 5, 3, 4)

SELECT p.PersonID,
    Case when spouse.PersonID is not null 
        THEN p.FirstName + ' and ' + spouse.FirstName + ' ' + p.LastName
    ELSE p.FirstName + ' ' + p.LastName END as ClientName,
    spouse.PersonID as RelatedPersonID
FROM Person p
LEFT JOIN Relationship r on p.PersonID = r.PersonID
LEFT JOIN Person spouse on r.RelatedPersonID = spouse.PersonID
WHERE r.Type = 3 OR spouse.PersonID is null

drop table Relationship
drop table Person

заблаговременно за помощь и время.

Примечание: Я редактировал свой макет script, чтобы включить 3, NoSpouse Morales, null в результаты. Кроме того, нет конкретных критериев, необходимых для мужа/жены. Тот, кто был выбран первым в списке, не должен включать связанного супруга.

Ответ 1

Если кто-то должен быть включен, а другой исключен, попробуйте добавить предложение

AND r.PersonID < r.RelatedPersonID 

так как идентификаторы не будут равны, и это будет включать только один:

 SELECT p.PersonID,
 Case when spouse.PersonID is not null 
    THEN p.FirstName + ' and ' + spouse.FirstName + ' ' + p.LastName
 ELSE p.FirstName + ' ' + p.LastName END as ClientName,
 spouse.PersonID as RelatedPersonID
FROM Person p
LEFT JOIN Relationship r on p.PersonID = r.PersonID
LEFT JOIN Person spouse on r.RelatedPersonID = spouse.PersonID
WHERE (r.Type = 3 AND r.PersonID < r.RelatedPersonID)  OR spouse.PersonID is null

Ответ 2

Это может работать

SELECT p.PersonID,
    Case when spouse.PersonID is not null 
        THEN p.FirstName + ' and ' + spouse.FirstName + ' ' + p.LastName
    ELSE p.FirstName + ' ' + p.LastName END as ClientName,
    spouse.PersonID as RelatedPersonID
FROM Person p
LEFT JOIN Relationship r on p.PersonID = r.PersonID and r.Type = 3
LEFT JOIN Person spouse on r.RelatedPersonID = spouse.PersonID
WHERE  coalesce(r.PersonID, 1) < coalesce(r.RelatedPersonID, 2)

Таким образом, вы учитываете только строки отношений, где PersonID меньше, чем RelatedPersonID, или строки, которые вообще не соединяются с таблицей Relationships (поскольку 1 < 2 всегда истинно)

Ответ 3

Если я правильно понимаю, вы можете просто удалить супругов в предложении WHERE:

SELECT PersonId, ClientName, RelatedPersonID
FROM (SELECT p.PersonID,
             (CASE WHEN spouse.PersonID is not null 
                   THEN p.FirstName + ' and ' + spouse.FirstName + ' ' + p.LastName
                   ELSE p.FirstName + ' ' + p.LastName
              END) as ClientName,
             spouse.PersonID as RelatedPersonID,
             spouse.LastName as spouse_lastname
      FROM Person p LEFT JOIN
           Relationship r 
           ON p.PersonID = r.PersonID LEFT JOIN
           Person spouse 
           ON r.RelatedPersonID = spouse.PersonID
      WHERE r.Type = 3 
     ) prs
WHERE spouse_LastName <> 'Wife';

Ответ 4

Попробуйте это

create table Person(
   PersonID int primary key,
   FirstName varchar(max),
   LastName varchar(max)
)
insert into Person values 
(1, 'John', 'Doe'), 
(2, 'Jane', 'Doe'), 
(3, 'NoSpouse', 'Morales'), 
(4, 'Jonathan', 'Brand'), 
(5,'Shiela','Wife')

create table Relationship (
   RelationshipID int,
   PersonID int references Person(PersonID),
   Type int,
   RelatedPersonID int references Person(PersonID)
)
insert into Relationship values 
(1, 1, 3, 2),
(2, 2, 3, 1),
(3, 4, 3, 5),
(4, 5, 3, 4)

SELECT p.PersonID,
   Case when spouse.PersonID is not null 
      THEN p.FirstName + ' and ' + spouse.FirstName + ' ' + p.LastName
   ELSE p.FirstName + ' ' + p.LastName END as ClientName,
   spouse.PersonID as RelatedPersonID
FROM Person p
LEFT JOIN Relationship r on p.PersonID = r.PersonID AND r.Type = 3 
LEFT JOIN Person spouse on r.RelatedPersonID = spouse.PersonID
WHERE r.RelationshipID IS NULL OR  r.RelationshipID < r.RelatedPersonID

drop table Relationship
drop table Person

Демо-ссылка: Rextester