Али, вот пример, который, по крайней мере, поможет вам начать. В SSMS вы можете запустить следующее.
Создайте некоторые переменные таблицы и вставьте ваши данные выборки.
DECLARE @ContactGroup TABLE ( id INT, title VARCHAR(50) );
INSERT INTO @ContactGroup ( id, title ) VALUES ( 1, 'Group A' );
DECLARE @ContactsInGroup TABLE ( ContactID INT, GroupID INT );
INSERT INTO @ContactsInGroup ( ContactID, GroupID ) VALUES ( 1, 1 ), ( 2, 1 ), ( 3, 1 );
DECLARE @ContactVariables TABLE ( id INT, [name] VARCHAR(50), GroupID INT, [Order] INT );
INSERT INTO @ContactVariables ( id, [name], GroupID, [Order] ) VALUES ( 1, 'Invoice', 1, 1 ), ( 2, 'Due Date', 1, 1 );
DECLARE @ContactsVariablesValues TABLE ( ContactVariableID INT, ContactID INT, [value] INT );
INSERT INTO @ContactsVariablesValues ( ContactVariableID, ContactID, [value] ) VALUES ( 1, 1, 600 );
Затем запросите данные следующим образом:
SELECT
ContactGroup.id AS GroupID
, ContactsInGroup.ContactID
, ContactVars.Invoice
, ContactVars.[Due Date]
FROM @ContactGroup AS ContactGroup
INNER JOIN @ContactsInGroup AS ContactsInGroup
ON ContactGroup.id = ContactsInGroup.GroupID
OUTER APPLY (
SELECT
[Invoice], [Due Date]
FROM (
SELECT
Vars.[name]
, Vals.[value]
FROM @ContactVariables AS Vars
LEFT OUTER JOIN @ContactsVariablesValues Vals
ON Vars.id = Vals.ContactVariableID
WHERE
Vars.GroupID = 1
AND Vals.ContactID = ContactsInGroup.ContactID
) AS ContactData
PIVOT (
MIN( [value] )
FOR [name] IN (
[Invoice], [Due Date]
)
) AS pvt
) AS ContactVars
ORDER BY
ContactGroup.id, ContactsInGroup.ContactID;
Что возвращает:
+---------+-----------+---------+----------+
| GroupID | ContactID | Invoice | Due Date |
+---------+-----------+---------+----------+
| 1 | 1 | 600 | NULL |
| 1 | 2 | NULL | NULL |
| 1 | 3 | NULL | NULL |
+---------+-----------+---------+----------+
На что обратить внимание
"Магия" здесь в НАРУЖНОМ ПРИМЕНЕНИИ. Это позволяет нам запрашивать подмножество данных на основе возвращенных первичных данных, в данном случае это GroupID и ContactID. OUTER APPLY также вернет строки со значениями NULL, как вы хотите.
Здесь у вас будут некоторые проблемы, а именно: чтобы использовать PIVOT, как показано в моем примере, вам нужно будет знать все значения (Invoice, Due Date и т.д. ...), которые станут заголовками столбцов. Основываясь на ваших настройках, я думаю, что это может быть не так, поэтому вы будете вынуждены прибегнуть к технике, которая создает и выполняет динамический оператор PIVOT для вас в OUTER APPLY.
Вы также можете рассмотреть возможность использования ТАБЛИЦЫ-ЗНАЧЕННОЙ ФУНКЦИИ, которая выполняет работу PIVOT, к которой затем можно присоединиться по сравнению с OUTER APPLY.
У вас есть несколько вариантов, но, надеюсь, это поможет вам быстрее начать думать.