2013-06-26 5 views
0

Я пытаюсь создать представление в SQL Server 2008 R2, где данные извлекаются из двух таблиц с двойными отношениями один к одному, и я хочу создать два столбца в представлении на основе значений из одного столбца в одной из таблиц.SQL Создание нескольких столбцов в представлении из одного столбца таблицы

Таблицы в настоящее время похожи на эти примеры:

TableA:

PrimaryKey | Name | Value_FK | Number_FK 
------------------------------------------- 
66   | NameA | 1   | 2 
77   | NameB | 3   | 4 

TableB:

PrimaryKey | Value 
------------------- 
1   | 238 
2   | 456 
3   | 100 
4   | 200 

Взгляд должен выглядеть следующим образом:

Name | Value | Number 
------------------------- 
NameA | 238 | 456 
NameB | 100 | 200 

(«Va lue 'и' Number ', по сути, одного и того же типа, и оба они находятся в столбце «Значение» в TableB. Я думал, что было бы легче дистанцироваться между «Value» и «Number», чем «ValueA» и «ValueB»).

Фактор, который должен решить, какие значения следует вводить в столбце «Значение» или «Номер столбца», является PrimaryKey в TableB и его ссылками в любом из иностранных ключей в TableA (но оба FK никогда не будут ссылаться на один и тот же ключ).

Это, скорее всего, не самая блестящая модель базы данных, имеющая двойственные отношения между таблицами. Однако это связано с отображением некоторых классов C# .NET в базу данных с использованием ADO.NET Entity Framework, где класс A имеет два объекта класса B (в данном случае с именем «Значение» и «Число») и модель базы данных в настоящее время создает две взаимосвязи из-за этого. Изменить это не вариант.

Я пробовал это, но мне трудно найти ответ, который мне нужен. Особенно, когда большинство результатов имеют обратное: выбор нескольких столбцов в один столбец.

Итак, как мне написать инструкцию Select?

CREATE VIEW ViewName 
AS 
SELECT DISTINCT a.Name as 'Name', ????? as 'Value', ????? as 'Number' 
FROM TableA a, TableB b 

Я довольно ржавый с расширенными командами SQL. Прошло более 1,5 лет с тех пор, как я вошел в нечто такое продвинутое. Я пытался что-то похожее на это: первый

CREATE VIEW ViewName 
AS 
WITH Name AS 
(SELECT DISTINCT a.Name FROM TableA a ) 

Value AS 
(
    SELECT DISTINCT b.Value as 'Value' FROM TableA a, TableB b 
WHERE b.PrimaryKey = an.ValueA_FK 
), 
Number AS 
(
    SELECT DISTINCT b.Value as 'Number' 
    FROM TableA a, TableB b 
    WHERE a.PrimaryKey = an.ValueB_PrimaryKey 
) 
SELECT DISTINCT 
    * FROM Name, Value, Number 

В результате моего совершенно неудачной попытки, как это:

Name | Value | Number 
------------------------- 
NameA | 100 | 200 
NameB | 100 | 200 
NameA | 100 | 456 
NameB | 100 | 456 
NameA | 238 | 200 
NameB | 238 | 200 
NameA | 238 | 456 
NameB | 238 | 456 

Теперь любой suggestiong как то, чтобы заполнить в запросе?

+0

Сначала никогда не используйте неявные соединения, они являются антипаттером SQL. Они, скорее всего, будут изношены и намного сложнее с течением времени поддерживать. Они также более 20 лет устарели. – HLGEM

ответ

4

Вы можете ссылаться на одну таблицу несколько раз в предложении FROM:

SELECT a.Name as 'Name', b1.Value as 'Value', b2.Value as 'Number' 
FROM TableA a 
    inner join TableB b1 
      on 
       a.Value_FK = b1.PrimaryKey 
    inner join TableB b2 
      on 
       a.Number_FK = b2.PrimaryKey 

Я также удалил DISTINCT, так как это не должно быть вашей привычкой, чтобы добавить один, и нет ничего в вопрос, который предполагает, что один необходим. Я также использовал соединения ANSI-Style.Это почти всегда предпочтительнее по сравнению со старым стилем (где таблицы в предложении FROM просто через запятую)


Если это возможно, что некоторые строки в TableA имеют NULLValue_FK или Number_FK, и вы все еще хотите эти строки в вашем представлении, вы бы переключили один или оба из inner join s на left join s. Затем вы также решите, должен ли выходной столбец быть NULL (в этом случае вы закончили) или какое-то другое значение (в этом случае у вас будет, например, COALESCE(b1.Value,<Value when null>) as 'Value').

+0

В этом случае вы должны обращаться к таблице более одного раза. Возможно, вам понадобятся левые соединения (и, как правило, делают это в такой структуре, поскольку нет гарантии соответствующей записи для любого типа данных). Это одна из причин, почему модель EAS таблицы deisgn является поирой. Если у вас есть 6 различных типов значений, хранящихся там, вам нужно шесть соединений. Если вы не знаете, сколько у вас будет, вы будете зависеть от динамического создания запроса (что, конечно, вы не можете сделать для представления). – HLGEM

+0

@HLGEM - у вас нет * have * to - вы можете присоединиться к нему один раз с предикатом, основанным на 'OR', а затем создать псевдоопределение с помощью' MAX (CASE ... ', чтобы затем разделить различные условия соединения в свои отдельные столбцы.Это не подход, который я бы рекомендовал, хотя. И вы можете быть прав, если захотите «LEFT JOIN's», но если это требование, OP не указал его. –

+0

Я только что поднял левый присоединитесь из-за вероятности, что это может потребоваться рассмотреть, а не потому, что я думал, что ваш код был неправильным. – HLGEM

0

Этот запрос даст результаты, которые вы хотите:

select t1.Name, value.Value, number.Value as Number 
from TableA t1 
inner join TableB value on value.PrimaryKey = t1.Value_FK 
inner join TableB number on number.PrimaryKey = t1.Number_FK 

вы чрезмерно сложным ваш запрос много.

+0

Возможно, слишком сложный, но это был псевдокод, показывающий только релевантные данные для проблемы. Реальный запрос намного больше. –