【问题标题】:SQL View: Join tables without causing the data to duplicate on every row?SQL 视图:连接表而不导致数据在每一行上重复?
【发布时间】:2011-06-29 21:31:05
【问题描述】:

每当我创建 3 个表的视图时,它都会复制所有行上的所有数据。我不知道如何加入这些,以便它显示空值而不是重复值。你能指出我正确的方向吗?

这是场景:

  • 表 1 = 帐户:帐户名称和帐户 ID
  • 表 2 = 属性:属性描述、属性地址和帐户 ID
  • 表 3 = 车辆:车辆制造商、车辆型号和帐户 ID

数据看起来像这样:

[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 上。

【问题讨论】:

  • 发布您正在使用的 SQL 怎么样...?
  • 将帐户加入属性为 Vehicles 中的列添加 NULL 值。将 Accounts 加入 Vehicles 为 Properties 中的列添加 NULL 值。将两者与union all结合起来
  • 马丁感谢您的回复。原来你说的正是我需要做的。

标签: sql-server sql-server-2008 join view duplicates


【解决方案1】:

在这种情况下,您需要使用 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

【讨论】:

  • 打败我。我推荐 UNION ALL,因为永远不会有重复,所以不要让 SQL 浪费时间检查它们。如果某些帐户可能没有属性或车辆,@Christopher 可能希望使用左外连接。
  • @Philip:得到了 UNION 的全部覆盖。同意左加入。
  • 哇...这个查询做了 3 件我以前从未见过的事情。联合并将列声明为 null 非常有意义。谢谢!然而,在那些“来自”的陈述中,你使用了一些我需要了解更多的魔法字母。当您说“来自帐户 a”时,a 是什么?几乎就像将 Accounts 表分配给变量一样?你可以说“on a.accountid”而不是“on a.accountid”吗?我将查询更改为使用完整的表名而不是“a”。 “页。” “诉”它似乎仍然有效。是简写吗?非常感谢。
  • 假设您将我的问题视为我对 SQL 知识水平的证明;我想知道您是否可以推荐一些您认为可以让我更上一层楼的额外阅读材料?如果我读过这本书,也许会给我回答这个问题的知识? (另外,由于我是服务器新手,它不会让我投票给答案。否则我会。再次感谢。)
  • @Christopher:我建议从 Itzik Ben-Gan 的 Microsoft SQL Server 2008 T-SQL Fundamentals 开始。他是著名的 SQL Server 权威和出色的作家。
【解决方案2】:

如果数据没有出现在当前查询的列中,它根本不会在该行上显示数据。

这对我来说没有意义(从某种意义上说,我不理解其含义,而不是说它是荒谬的)。

您看到第二个数据的原因是车辆和财产之间没有关系。你拥有的是这样的:

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

【讨论】:

  • 亚当谢谢你;你的解释帮助我更清楚地思考。我试图投票,但显然我还没有足够的声誉来投票。
猜你喜欢
  • 2012-03-28
  • 2020-10-30
  • 2018-12-12
  • 2020-11-12
  • 1970-01-01
  • 1970-01-01
  • 2015-08-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多