【问题标题】:Conditional joins in MS SQL serverMS SQL 服务器中的条件连接
【发布时间】:2019-02-11 21:24:52
【问题描述】:

我正在尝试做一个我认为是简单的条件连接的事情,我看到了这个 (SQL server conditional join),它是关闭的,但不是我需要的。我不擅长解释,所以我会尽力举例说明。

设备表:(dev_tbl) dev_id dev_ip 名称 1 192.168.1.10 Core_SW_1 2 192.168.20.5 访问_SW_1 3 192.168.240.1 远程_SW_1 附加数据表:(dev_append) id append_id dev_id append_value 1 8 1 123 玫瑰花蕾 Ln。 2 9 1 个人 3 10 1 管理员 4 8 3 2500 国家公路 5 9 3 我自己 6 10 3 一些用户 附加数据默认值:(dev_append_def) id append_id field_name default_value 1 8 地址无线索 2 9 dev_owner a.person 3 10 audit_by 没人

当前 SQL 查询:

SELECT dev_tbl.dev_ip, dev_tbl.dev_name, dev_append.append_value, dev_append_def.field_name
FROM dev_tbl 
LEFT JOIN dev_append ON (dev_tbl.dev_id = dev_append.dev_id) 
RIGHT JOIN dev_append_def ON (dev_append.append_id = dev_append_def.append_id)

当 dev_append 中有条目时,上面的代码为我提供了所有必要的信息,但正如您所见,它为没有条目的设备返回一个“null”条目。

192.168.1.10   Core_SW_1    123 Rosebud Ln.     Address
192.168.1.10   Core_SW_1    a.person            dev_owner
192.168.1.10   Core_SW_1    admin               audit_by
192.168.20.5   Access_SW_1  NULL                NULL
192.168.240.1  Remote_SW_1  2500 National Pkwy  Address
192.168.240.1  Remote_SW_1  my.self             dev_owner
192.168.240.1  Remote_SW_1  some.user           audit_by

我的挂断是我需要从 dev_append_def 获取 field_name 和 default_value IF dev_append 中没有特定于设备的条目,因此输出如下所示。

192.168.1.10   Core_SW_1    123 Rosebud Ln.     Address
192.168.1.10   Core_SW_1    a.person            dev_owner
192.168.1.10   Core_SW_1    admin               audit_by
192.168.20.5   Access_SW_1  NoClue              Address
192.168.20.5   Access_SW_1  a.person            dev_owner
192.168.20.5   Access_SW_1  nobody              audit_by
192.168.240.1  Remote_SW_1  2500 National Pkwy  Address
192.168.240.1  Remote_SW_1  my.self             dev_owner
192.168.240.1  Remote_SW_1  some.user           audit_by

我会像往常一样在包含数组的程序中简单地执行此操作,但我想使用此信息创建一个数据库视图。如果做不到,那也没关系,我会开发一个 Java 应用程序或 PHP 网页。

【问题讨论】:

  • 右连接不应该是左连接吗?
  • 在这种特殊情况下应该没关系,但如果我得到不寻常的结果,那就太好了。

标签: sql-server


【解决方案1】:

您需要创建所有可能行的笛卡尔积,然后加入可用值。

SELECT d.dev_ip, 
    d.dev_name, 
    COALESCE( d.append_value, dad.default_value) AS append_value,
    dad.field_name
FROM dev_tbl d
CROSS JOIN dev_append_def dad
LEFT JOIN dev_append da ON d.dev_id = da.dev_id
                    AND dad.append_id = da.append_id;

【讨论】:

  • 您介意稍微解释一下 SQL 吗?我不是 100% 理解 COALESCE 语句如何与交叉连接一起工作,也不知道它如何知道更喜欢 dev_append 中的数据而不是 dev_append_def
  • dev_tbl 使用交叉连接与 dev_append_def 连接以获取所有可能的值和默认值(这将为您提供 9 行(3 行 * 3 行))。 dev_append 的左连接保留所有 9 行,并在它存在的地方添加 append_value,如果它不存在,它将为 NULL。 COALESCE 将获取第一个非空值并将其用作输出值,在这种情况下,当没有 append_value 时,它​​将始终有一个 default_value(至少对于您给出的示例,因为 default_value 永远不会为空)。 @AaronBaxter
【解决方案2】:

我不知道您的数据模型,但对我来说,如果设备没有 dev_append 条目,那么默认值应该链接到 dev_tbl 而不是 dev_append 会更自然。无论如何,正如我所说,我现在不知道你的要求,所以你可能是对的。

所以这里是你的 SELECT,它会给你你想要的:

SELECT dev_tbl.dev_ip, dev_tbl.name, dev_append.append_value, dev_append_def.field_name
  FROM dev_tbl 
  LEFT JOIN dev_append
    ON (dev_tbl.dev_id = dev_append.dev_id) 
  JOIN dev_append_def
    ON (dev_append.append_id = dev_append_def.append_id)

UNION

SELECT dev_tbl.dev_ip, dev_tbl.name, dev_append_def.default_value, dev_append_def.field_name
  FROM dev_tbl
  JOIN dev_append_def 
    ON 1 = 1
 WHERE not exists (select 1 FROM dev_append where dev_append.dev_id = dev_tbl.dev_id)

请注意,我使用 Oracle 对其进行了测试,但它在 SQL Server 上也应该没有问题

【讨论】:

    猜你喜欢
    • 2013-06-17
    • 1970-01-01
    • 2023-03-11
    • 2010-11-07
    • 2016-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-29
    • 2022-01-03
    相关资源
    最近更新 更多