Представление SQL: соединять таблицы, не вызывая дублирования данных в каждой строке?

Всякий раз, когда я создаю представление из 3 таблиц, оно дублирует все данные во всех строках. Я не понимаю, как объединить их, чтобы вместо дубликатов отображались нули. Можете ли вы указать мне в правильном направлении?

Вот сценарий:

  • Таблица 1 = Учетные записи: имена учетных записей и идентификаторы учетных записей
  • Таблица 2 = Свойства: описание свойства, адрес свойства и идентификатор учетной записи
  • Таблица 3 = Транспортные средства: марка транспортного средства, модель транспортного средства и идентификатор учетной записи

Данные выглядят примерно так:

[Table 1= Accounts]
   id name  accountid

   1 Family A  account001
   2 Family B  account002
   3 Family C  account003



[Table 2= Properties]
  id accountid  description address

  1 account001 home california
  2 account001  beach mexico
  3 account002  hideout arizona
  4 account002  getaway nevada
  5 account002  skilodge idaho
  6 account 003  home texas


[Table 3= Vehicles]

 id description make model accountid
  1 green  Acura Integra  account001
  2 blue  Aston Martin Vantage account001
  3 silver  Audi Quattro  account001
  4 work  Bently Continental GTC account002
  5 kids  Ford Fusion Hybrid account002
  6 Mom's Car  Land Rover LR4 account003
  7 Paper Weight Mini Clubman account003
  8 Beater  Dodge Caliber  account003
  9 Why Mahindra TR40 account003
  10 Kids  Scion xB  account003

Я хочу создать представление, которое показывает мне все записи в БД. Для каждой строки я хотел бы показать имя учетной записи, а затем данные из таблиц.

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

account_Name | property_DESCRIPTION | property_ADDRESS | vehicles_DESCRIPTION   vehicles_MAKE | vehicles_MODEL

- Family A  home    california  **null  null    null**
- Family A  beach   mexico  **null  null    null**
- Family A  **null  null**  blue    Aston Martin    Vantage
- Family A  **null  null**  silver  Audi    Quattro
- Family B  hideout arizona **null  null    null**
- Family B  getaway nevada  **null  null    null**
- Family B  skilodge    idaho   **null  null    null**
- Family B  **null  null**  kids    Ford    Fusion Hybrid

Но вместо этого он отображает дубликаты данных, как показано ниже, где каждый раз, когда он находит новые записи, он заполняет строку данными из других таблиц.

account_Name    property_DESCRIPTION    property_ADDRESS    vehicles_DESCRIPTION    vehicles_MAKE   vehicles_MODEL

- Family A  home    california  green   Acura   Integra
- Family A  beach   mexico  green   Acura   Integra
- Family A  home    california  blue    Aston Martin    Vantage
- Family A  beach   mexico  blue    Aston Martin    Vantage
- Family A  home    california  silver  Audi    Quattro
- Family A  beach   mexico  silver  Audi    Quattro
- Family B  hideout arizona work    Bently  Continental GTC
- Family B  getaway nevada  work    Bently  Continental GTC
- Family B  skilodge    idaho   work    Bently  Continental GTC
- Family B  hideout arizona kids    Ford    Fusion Hybrid
- Family B  getaway nevada  kids    Ford    Fusion Hybrid
- Family B  skilodge    idaho   kids    Ford    Fusion Hybrid

Почему это происходит, мне кажется, имеет смысл; все дело в стыках. Как будто соединения чувствуют, что им действительно нужно отображать данные независимо от стоимости. Думая с точки зрения сценариев, кажется, что вместо объединений мне нужно прокручивать таблицу по отдельности, а затем объединять полученные циклы вместе.

По сути, мне нужно, чтобы представление сначала отображало все записи из таблицы 1, затем все записи из таблицы 2, затем все записи из таблицы 3. Я действительно не хочу объединять эти данные вместе; Я просто хочу увидеть все это в одном представлении.

Может ли кто-нибудь подсказать мне, как создать желаемое представление выше, которое показывает нули вместо дубликатов?

Это на SQL 2008 R2 Enterprise.


person Christopher    schedule 18.02.2011    source источник
comment
Как насчет публикации SQL, который вы используете...?   -  person Adam Robinson    schedule 18.02.2011
comment
Присоединение учетных записей к свойствам добавляет значения NULL для столбцов в транспортных средствах. Присоединение учетных записей к транспортным средствам добавляет значения NULL для столбцов в свойствах. Объедините два с union all   -  person Martin Smith    schedule 18.02.2011
comment
Мартин спасибо за ответ. Оказывается, то, что вы сказали, именно то, что мне нужно было сделать.   -  person Christopher    schedule 18.02.2011


Ответы (2)


В этом случае вам нужно будет использовать UNION (фактически UNION ALL).

select a.name as account_Name, 
       p.description as property_DESCRIPTION, 
       p.address as property_ADDRESS, 
       null as vehicles_DESCRIPTION,
       null as vehicles_MAKE, 
       null as vehicles_MODEL
    from Accounts a
        inner join Properties p
            on a.accountid = p.accountid
UNION ALL   
select a.name as account_Name, 
       null as property_DESCRIPTION, 
       null as property_ADDRESS, 
       v.description as vehicles_DESCRIPTION,
       v.make as vehicles_MAKE, 
       v.model as vehicles_MODEL
    from Accounts a
        inner join vehicles v
            on a.accountid = v.accountid
person Joe Stefanelli    schedule 18.02.2011
comment
Ударь меня. Я бы рекомендовал UNION ALL, так как никогда не будет дубликатов, поэтому не тратьте время SQL на их проверку. В зависимости от этого @Christopher может захотеть использовать левое внешнее соединение, если у некоторых учетных записей может не быть свойств или транспортных средств. - person Philip Kelley; 18.02.2011
comment
@Philip: У вас есть СОЮЗ ВСЕХ. Согласитесь на левое соединение. - person Joe Stefanelli; 18.02.2011
comment
Вау... этот запрос делает 3 вещи, которых я никогда раньше не видел. Объединение и объявление столбца нулевым имеет смысл. СПАСИБО! Однако в этих утверждениях «от» вы используете какие-то волшебные буквы, о которых мне нужно узнать больше. Когда вы говорите From Accounts a, что такое a? Это почти как присваивание таблицы Accounts переменной? Вместо a.accountid не могли бы вы сказать Accounts.accountid? Я изменил запрос, чтобы использовать полное имя таблицы вместо a. п. v. и вроде как до сих пор работает. Это стенография? Огромное спасибо. - person Christopher; 18.02.2011
comment
Предполагая, что вы видите мой вопрос как свидетельство моего уровня знаний SQL; Интересно, не могли бы вы порекомендовать какую-нибудь дополнительную литературу, которая, по вашему мнению, могла бы поднять меня на следующий уровень? Возможно, книга, которая дала бы мне знания для ответа на этот вопрос, если бы я ее прочитал? (Кроме того, поскольку я новичок на сервере, это не позволит мне проголосовать за ответ. В противном случае я бы сделал это. Еще раз спасибо.) - person Christopher; 18.02.2011
comment
@Christopher: Да, a называется псевдонимом таблицы и, как вы догадались, является просто сокращенным способом ссылки на таблицу в других местах запроса. - person Joe Stefanelli; 18.02.2011
comment
@Christopher: я бы рекомендовал начать с Microsoft Ицика Бен-Гана. Основы SQL Server 2008 T-SQL. Он известный авторитет в области SQL Server и превосходный писатель. - person Joe Stefanelli; 18.02.2011

Где он просто не отображает данные в строке, если эти данные не пришли в столбец, который он запрашивал в данный момент.

Для меня это не имеет смысла (в том смысле, что я не понимаю смысла, а не в том, что это бессмысленно).

Причина, по которой вы видите данные во втором, заключается в том, что нет связи между транспортным средством и имуществом. Что у вас есть это:

Vehicles *-----| Account | -----* Properties

У учетной записи много транспортных средств, а у учетной записи много свойств; однако между транспортным средством и имуществом нет никакой связи, поэтому, если бы вы сделали что-то вроде этого:

select
    *

from account a

join property p on p.accountid = a.accountid
join vehicle v on v.accountid = a.accountid

Ваше представление будет содержать строку для каждой комбинации транспортного средства и собственности в данной учетной записи (которую вы, похоже, видите).

Если вы ищете список учетных записей со списком свойств и список транспортных средств (без связи между ними), вам нужно создать два отдельных запроса и объединить их с union.

select
    a.accountid,
    p.property_name,
    null as vehicle_name

from account a

join property p on p.accountid = a.accountid

union

select
    a.accountid,
    null as property_name,
    v.vehicle_name

from account a

join property p on p.accountid = a.accountid
join vehicle v on v.accountid = a.accountid
person Adam Robinson    schedule 18.02.2011
comment
Адам спасибо; ваше объяснение помогает мне яснее обдумать это. Я пытался проголосовать за это, но, видимо, у меня еще недостаточно репутации для этого. - person Christopher; 18.02.2011