Как объединить эти таблицы для полного набора результатов из всех таблиц? - PullRequest
3 голосов
/ 01 мая 2019

У меня есть таблица A для сущностей

У меня есть таблица B для предметов

У меня есть таблица C для сущностей и связанные с ними настроенные значения.

I 'Я хочу написать представление, которое будет возвращать мне строки с каждой комбинацией Entity + Item, и использовать данные из таблицы C, если они существуют.

Кроме того, если в TableC есть элементы, которых нет в TableB, я бы также хотел, чтобы они были

Например,

Table A 
Entity 1
Entity 2

Table B
Item X
Item Y
Item Z

Table C
Entity 1    Item X    True
Entity 1    Item Y    False
Entity 2    Item X    False
Entity 2    Item J    False


Result Table Wanted
Entity 1    Item X    True
Entity 1    Item Y    False
Entity 1    Item Z    Null
Entity 2    Item X    False
Entity 2    Item Y    Null
Entity 2    Item Z    Null
Entity 2    Item J    False

По какой-то причине ярисую бланк для этого.Прошло много времени с тех пор, как я работал с SQL, поэтому, возможно, я упускаю что-то очевидное.Может ли кто-нибудь помочь мне определить синтаксис, который мне нужен для написания этого запроса?

Я подошел ближе, используя CROSS JOIN

SELECT *
FROM Entities
CROSS JOIN Items
LEFT OUTER JOIN EntityItems 
    ON Entities.ID = EntityItems.EntityID
    AND Items.ID = EntityItems.ItemID

Это возвращает мне все, кроме строки в таблице C для ItemJ.

Обновление: поцарапайте, это на самом деле возвращает мне слишком много строк.Это то, с чем я сейчас играю.

Я использую MS Sql Server 2017

1 Ответ

2 голосов
/ 01 мая 2019

Ваш cross join / left join является правильным подходом:

SELECT e.EntityID, i.ItemId, COALESCE(ei.value, 'false') as value
FROM Entities e CROSS JOIN
     Items i LEFT JOIN
     EntityItems ei
    ON e.ID = ei.EntityID AND
       i.ID = ei.ItemID;

Однако это предполагает, что ItemId правильно определено с отношением внешнего ключа.Вы, кажется, недействительными ItemId с.Вы можете исправить это:

SELECT e.EntityID, i.ItemId, COALESCE(ei.value, 'false') as value
FROM Entities e CROSS JOIN
     (SELECT i.ItemId
      FROM Items i
      UNION  -- on purpose to remove duplicates
      SELECT ei.ItemId
      FROM EntityItems ei
     ) i LEFT JOIN
     EntityItems ei
    ON e.ID = ei.EntityID AND
       i.ID = ei.ItemID;

Однако я настоятельно рекомендую вам исправить ваши данные (т.е. добавить J в таблицу предметов) и добавить:

alter table entityitems add constraint fk_entityitems_entityid
    foreign key (entityid) references entities(entityid);

alter table entityitems add constraint fk_entityitems_itemid
    foreign key (itemid) references entities(itemid);

Это поможет вам обеспечить целостность данных (движение вперед) - после того, как вы исправили данные.

РЕДАКТИРОВАТЬ:

Ах, вы не хотите, чтобы идентификаторы дополнительных элементов были на всехсущности.Если так:

SELECT e.EntityID, i.ItemId, COALESCE(ei.value, 'false') as value
FROM Entities e CROSS JOIN
     Items i LEFT JOIN
     EntityItems ei
    ON e.ID = ei.EntityID AND
       i.ID = ei.ItemID;
UNION ALL
SELECT ei.EntityId, ei.ItemId, ei.value
FROM EntityItems ei
WHERE NOT EXISTS (SELECT 1 FROM Items i WHERE i.ItemId = ei.ItemId);
...