通过跨多个表的连接处理空值

时间:2014-06-16 18:49:37

标签: sql sql-server tsql

我的思绪现在正在爆炸......我无法以我想要的方式工作! SQL严重如此痛苦。 (/ End Rant)

我有三个表可以链接一些常用列。我试图根据最远表中的代码,根据中间表中的名称从一个表中检索ID。 (请原谅我的词汇,我不熟悉SQL或它的语言)如果最远的表有中间表中找不到的代码,则默认为某个值。然后,第一个表将返回空值的默认值。等

实施例,

  • tblCounty表格包含IDname列。我将根据与ID tblCounty列匹配的name列,从name返回tblCode
  • tblCode有两列namecodetblCode根据匹配的name列与code的{​​{1}}列返回相应的tblAddress
  • code有很多列,但共享一个代码字段。

我的尝试,

tblAdress

我收到的错误是:

  

子查询返回的值超过1。当子查询遵循=,!=,<,< =,>,> =或子查询用作表达式时,不允许这样做。

现在我当然搜索了这个并查看了StackOverflow上的结果,但我无法应用我发现的问题。

供应商

INSERT INTO vendor (CountyID, Contact)
  SELECT 
     (SELECT a.id 
      FROM county a 
      WHERE a.name = (CASE WHEN (SELECT TOP(1) c.countyID 
                                 FROM tblAdress c 
                                 INNER JOIN tblCode d ON c.CountyID = d.CodeID 
                                 WHERE d.CodeID = b.CountyID) IS NULL THEN '**NONE**' 
                           ELSE (SELECT a.CodeName 
                                 FROM tblCode a 
                                 WHERE a.CodeID = b.CountyID) END)),
     b.Contact
  FROM 
     tblAdress b

tblCounty

CountyID  |  .... 
-------------------
1         | ... 
2         | ... 
3         | ... 
2         | ... 

tblCode

ID   |   Name  | ...
----------------------
1    | **None** 
2    |  NYC 
3    |  Buffalo 

tblAdress

 Name     |  Code
 --------------
 **None** |  **None** 
 NYC      |    56A 
 Buffalo  |    75B

使用上面的表格,我想将Code | .... ---------------- **None** | .... 56A | ...... 75B | ..... 56A | ..... 之外的所有数据传输到另一个表(tblAdress)。在此过程中,我将通过vendor比较将列Code转换为tblCode的列name,然后通过code转换为tblCounty.ID比较。

基本上需要全部捕获。如果name中的tblAddress中的代码不存在,或tblCode中的代码为空,则会返回默认值(tblAddress)。然后None会将该默认值转换为tblCounty,然后将其存储到ID = 1表中。

修改

Vendor

3 个答案:

答案 0 :(得分:1)

首先,您的数据库似乎没有遵循创建数据库的最佳做法。

理想情况下,关系和表的设计应该可以防止您必须在连接中进行空检查,并且大多数情况下,简单的左连接可以完成您想要的大部分操作。在添加数据时是否可以使用约束和ISNULL来确保其完整性?另外,如果可以的话,我建议不要像像县一样加入表格 - 使用整数主键会更优雅。

我建议您在进行之前确保您的设计是可靠的,因为这些问题可能会在将来成倍增加。

话虽如此,如果您坚持继续前进的方式,以下查询应该做您想做的事情:

SELECT  tblCounty.ID, 
    ISNULL(tblAddress.Code, 'none')
    --Whatever you want to select
FROM tblCounty
LEFT JOIN tblCode ON tblCounty.Name = tblCode.Name
    LEFT JOIN tblAddres ON ISNULL(tblCode.Code, 'none') = ISNULL(tblAddress.Code, 'none')

答案 1 :(得分:0)

这不会得到你想要的结果吗?

select isnull(a.ID, '**NONE**') as CountyID, c.Contact
from tblCounty a
left join tblCode b on a.Name = b.Name
left join tblAddress c on b.Code = c.Code

答案 2 :(得分:0)

好的,让我们尝试构建此查询:

    来自tblCounty
  • ,您想要ID?
  • tblCountytblCode是否通过name列进行了关联? (糟糕的主意 - 打开各种问题 - 我宁愿使用code或其他东西!)
  • tblAdress通过tblCode
  • code相关联

右?

好的,让我们试试这个:

  • 如果你想"链接"两个具有共同列的表,并且您只希望两个表中都存在行 - 使用INNER JOIN
  • 如果你想"链接"两个表格有一个共同的列,你想要所有的行,甚至是那些不存在于"右边的行#34;表,使用LEFT OUTER JOIN

所以我说你需要这样的东西:

SELECT
   c.ID, c.Name, ...(whatever other columns you want),
   -- if there's no entry in `tblAddress`, then `a.Name` will be `NULL`
   -- so just replace that `NULL` with your default value
   ISNULL(a.Name, '*DEFAULT NAME*')
FROM
   dbo.tblCounty c
INNER JOIN
   dbo.tblCode cd ON c.Name = cd.Name
LEFT OUTER JOIN
   dbo.tblAddress a ON cd.Code = a.Code

更新:好的,所以我尝试了您的示例数据 - 这个查询怎么样?

SELECT
    c.ID, cd.Code, 
    a.StreetName
FROM 
    dbo.tblAdress a
LEFT OUTER JOIN 
    dbo.tblCode cd ON ISNULL(a.Code, 'None') = cd.COde
LEFT OUTER JOIN 
    dbo.tblCounty c ON c.NAME = cd.NAME