2016-12-01 3 views
1

Это меня сходит с ума, и это может быть даже невозможно. У меня есть четыре таблицы, перечисленные ниже. Для краткости я удалил несущественные столбцы, индексы, ключи, внешние ключи и т.д.SQL Server условное соединение четырех таблиц в представлении

CREATE TABLE Client(
    ClientID uniqueidentifier ROWGUIDCOL NOT NULL DEFAULT (newid()), 
    ClientName varchar(250) not null 
); 
GO 

CREATE TABLE Instance(
    InstanceID uniqueidentifier ROWGUIDCOL NOT NULL DEFAULT (newid()), 
    ClientID uniqueidentifier not null, /* FK into Client */ 
    InstanceName varchar(48) not null 
); 
GO 

CREATE TABLE Object(
    ObjectID uniqueidentifier ROWGUIDCOL NOT NULL DEFAULT (newid()), 
    ClientID uniqueidentifier not null, /* FK into Client */ 
    InstanceID uniqueidentifier null, /* FK into Instance */ 
    Path varchar(260) not null 
); 
GO 

CREATE TABLE History(
    Timestamp datetime DEFAULT (getdate()), 
    ClientID uniqueidentifier null,  /* if not null, references Client */ 
    InstanceID uniqueidentifier null, /* if not null, references Instance */ 
    ObjectID uniqueidentifier null,  /* if not null, references Object */ 
    Details varchar(1024) 
); 
GO 

Я пытаюсь создать представление на столе истории. Трудный столбец в представлении - ClientName. Если History.ClientID не является нулевым, это легко. Но если History.ClientID равен null, но ObjectID не равен null, тогда ему необходимо получить имя_пользователя через History.ObjectID-> Object.ClientID-> Client.ClientName.

Это лучшее, что я могу придумать, которое работает, если History.ClientID не является нулевым, но я понятия не имею, как получить ClientName с помощью ObjectID, если History.ClientID равно null. Надеюсь, это все понятно.

CREATE VIEW History_Report as 
SELECT 
     H.TimeStamp, 
     C.ClientName, 
     Q.InstanceName, 
     O.Path, 
     H.Details 
from 
    History H 
    left join Instance Q ON (H.InstanceID = Q.InstanceID) 
    left join Object O on (H.ObjectID = O.ObjectID) 
    left join Client C on (H.ClientID = C.ClientID) 
GO 

Это лучше всего сделать с помощью курсоров?

ответ

1

Я думаю, что вы имеете в виду что-то вроде этого:

CREATE VIEW History_Report as 
SELECT 
     H.TimeStamp, 
     COALESCE(C.ClientName, CO.ClientName) ClientName, 
     Q.InstanceName, 
     O.Path, 
     H.Details 
from 
    History H 
    left join Instance Q ON (H.InstanceID = Q.InstanceID) 
    left join Object O on (H.ObjectID = O.ObjectID) 
    left join Client C on (H.ClientID = C.ClientID) 
    LEFT JOIN Client CO ON (O.ClientID = CO.ClientID) 
GO 
+0

Блестящий! Благодарю. Я забыл о COALESCE. –

1

Простой подход, чтобы просто добавить дополнительный join в вашем запросе:

CREATE VIEW History_Report as 
SELECT 
     H.TimeStamp, 
     isnull(C.ClientName, CO.ClientName) as ClientName, 
     Q.InstanceName, 
     O.Path, 
     H.Details 
from History H 
    left join Instance Q 
     on(H.InstanceID = Q.InstanceID) 
    left join Object O 
     on(H.ObjectID = O.ObjectID) 
    left join Client C 
     on(H.ClientID = C.ClientID) 
    left join Client CO 
     on(O.ClientID = CO.ClientID 
      and H.ClientID is null -- This will help limit duplicates 
     ) 
GO 

Хотя вам нужно будет следить за дубликатами, когда Таким образом вы добавляете дополнительные join s. Не видя ваших данных, мы не можем сказать точно.

Смежные вопросы