2015-01-21 49 views
2

我有两张桌子。自我加入并忽略一张桌子/一面的空值只有

一个表定义客户连接:

CREATE TABLE IF NOT EXISTS `cust_connections` (
    `id` int(11) NOT NULL, 
     `short_name` char(15) COLLATE utf8_unicode_ci NOT NULL, 
     `source_fnn` char(10) COLLATE utf8_unicode_ci NOT NULL, 
     `dest_fnn` char(10) COLLATE utf8_unicode_ci NOT NULL, 
     `service_type` char(32) COLLATE utf8_unicode_ci NOT NULL, 
     `ladder_side` char(10) COLLATE utf8_unicode_ci NOT NULL 
    ) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

    INSERT INTO `cust_connections` (`id`, `short_name`, `source_fnn`, `dest_fnn`, `service_type`, `ladder_side`) VALUES 
    (1, 'cust1', 'N2843453A', '', 'HD_300_Connect', 'src only'), 
    (2, 'cust2', '', 'N2843600A', 'HD_300_Connect', 'dest only'), 
    (3, 'cust3', 'N2720257O', 'N2731164O', 'DVB25_188byte', 'both'), 
    (4, 'cust4', 'N27xxx7O', 'N2731164O', 'DVB25_188byte', 'src ukn'), 
    (5, 'cust4', 'N27xxx7O', '', 'DVB25_188byte', 'ukn +blk'); 

ALTER TABLE `cust_connections` 
ADD PRIMARY KEY (`id`); 

ALTER TABLE `cust_connections` 
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=18; 

其他表定义了设备:

 CREATE TABLE IF NOT EXISTS `cust_port` (
    `id` smallint(11) NOT NULL, 
     `system_name` char(32) COLLATE utf8_unicode_ci NOT NULL, 
     `slot_no` char(2) COLLATE utf8_unicode_ci NOT NULL, 
     `port_no` char(2) COLLATE utf8_unicode_ci NOT NULL, 
     `port_fnn` char(9) COLLATE utf8_unicode_ci NOT NULL 
    ) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

    INSERT INTO `cust_port` (`id`, `system_name`, `slot_no`, `port_no`, `port_fnn`) VALUES 
    (1, '01-06C2:source', '7', '1', 'N2843453A'), 
    (2, '01-27B4:dest', '1', '2', 'N2843600A'), 
    (3, '01-27B6:source+dst', '17', '3', 'N2720257O'), 
    (4, '01-27B6:dst+src', '17', '3', 'N2731164O'), 
    (5, '01-32C6:dup_fnn1', '1', '2', 'N2845070O'), 
    (26, '01-32C6:dup_fnn2', '1', '3', 'N2845070O'), 
    (27, '01-32D6:no_fnn', '1', '4', ''), 
    (28, '01-32D6:diff_fnn', '1', '4', 'x123456'); 

ALTER TABLE `cust_port` 
ADD PRIMARY KEY (`id`); 

ALTER TABLE `cust_port` 
MODIFY `id` smallint(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=29; 

SQL结果是:

cc_id short_name source_fnn dest_fnn service_type ladder_side  src_system_name  src_slot_no  src_port_no  src_port_fnn dst_system_name  dst_slot_no  dst_port_no  dst_port_fnn  
1  cust1  N2843453A    HD_300_Connect src only  01-06C2:source   7     1   N2843453A  01-32D6:no_fnn  1    4 
2  cust2  N2843600A    HD_300_Connect dest only  01-32D6:no_fnn   1     4       01-27B4:dest   1    2    N2843600A 
3  cust3  N2720257O N2731164O DVB25_188byte both   01-27B6:source+dst 17     3   N2720257O  01-27B6:dst+src  17    3    N2731164O 
4  cust4  N27xxx7O N2731164O DVB25_188byte src ukn  NULL     NULL    NULL  NULL   01-27B6:dst+src  17    3    N2731164O 
5  cust4  N27xxx7O    DVB25_188byte ukn +blk  NULL     NULL    NULL  NULL   01-32D6:no_fnn  1    4 

我做的两个联接表。

问题是,如果port_fnn为null,我想排除该行,但如果客户源或目标fnns中的任何一个为null,则显示该行。

我正在做一个左(自我)加入,以匹配源fnns和目标fnns对设备fnn。不幸的是,我的客户fnns必须能够具有空值。

如果设备表中没有空值,我的查询很好用。 我的查询是:

SELECT 
cc.id AS cc_id, short_name,source_fnn, dest_fnn, service_type,ladder_side, 
src.system_name AS src_system_name, 
src.slot_no AS src_slot_no, 
src.port_no AS src_port_no, 
src.port_fnn AS src_port_fnn, 
dst.system_name AS dst_system_name, 
dst.slot_no AS dst_slot_no, 
dst.port_no AS dst_port_no, 
dst.port_fnn AS dst_port_fnn 
FROM cust_connections cc 
LEFT JOIN cust_port src on cc.source_fnn=src.port_fnn 
LEFT JOIN cust_port dst on cc.dest_fnn=dst.port_fnn 

在我的结果集: 行1 - 具有源FNN只。我想要的结果是空的目标字段,即:

cc_id short_name source_fnn dest_fnn service_type ladder_side  src_system_name  src_slot_no  src_port_no  src_port_fnn dst_system_name  dst_slot_no  dst_port_no  dst_port_fnn  
1  cust1  N2843453A    HD_300_Connect src only  01-06C2:source   7     1   N2843453A  NULL    NULL    NULL   NULL 

查询被检测空FNN与不具有相关联的模糊神经网络的设备填充。 I.e .: 01-32D6:no_fnn。对于source_system_name发生

同样的问题在第2行和dst_system_name上行5.

+0

不要ü希望从设备表中排除port_fnn? – WisdmLabs 2015-01-21 06:14:37

+1

这个例子会是你期望的结果吗?你还可以保持查询和数据之间的表名相同吗?它有点混乱 – 2015-01-21 06:43:54

+1

@Nigel,我只是看着你想要的结果。它与您查询的结果相同,除了一件事情,您在最后一行中表示您不希望获得任何数据的行中的数据。又名'equip4 4/2'这是从你说你希望它不被显示的行,因为它有一个空port_fnn – 2015-01-21 08:47:24

回答

1

''(空字符串)不为空。 (其中sqlfiddle输出为“(null)”。)

在文本中,请不要写“NULL”或“< NULL>”或“null”或“(null)”来引用空字符串最初在你的问题。清楚什么是'',什么是NULL。

''=''但是NULL <> NULL。因此,当相等性测试涉及“'时,您的LEFT JOIN在列cc.source_fnn和src.port_fnn之间以及列cc.dest_fnn和cust_port port_fnn之间找到匹配。但是你不想让LEFT JOIN匹配那些行。

可以说,通过:

  1. 宣布所有_fnn列空的,即作为NULL(默认值),而不是NOT NULL,并在你的表,你现在用“使用NULL”(空字符串)。然后你的查询会给出正确的答案!

  2. 需要port_fnn <> '':

    FROM cust_connections cc 
    LEFT JOIN cust_port src 
    ON cc.source_fnn=src.port_fnn AND cc.source_fnn <> '' 
    LEFT JOIN cust_port dst 
    ON cc.dest_fnn=dst.port_fnn AND cc.dest_fnn <> ''; 
    
  3. 从cust_port删除这些行之前,你留下了它JOIN:

    FROM cust_connections cc 
    LEFT JOIN 
        (SELECT * FROM cust_port WHERE port_fnn <> '' 
        ) src 
    ON cc.source_fnn=src.port_fnn 
    LEFT JOIN 
        (SELECT * FROM cust_port WHERE port_fnn <> '' 
        ) dst 
    ON cc.dest_fnn=dst.port_fnn; 
    

Sqlfiddle for 1 using NULLfor 2 & 3 using ''。这些行添加了第二个cust_port行,缺少port_fnn以显示以上提供了正确的结果。您的查询与''错误地生成其他虚假的行。

如果你想从左边空JOIN显示为输出空字符串,那么你可以使用IFNULL这些列:

IFNULL(dst.port_fnn,“”)AS dst_port_fnn

+0

非常感谢你 - 这工作。我已经和2一起加入了IFNULL(dst.port_fnn,'')AS dst_port_fnn以涵盖NULL和''可能性。 – Nigel 2015-01-22 05:36:46

0

[本答案是的qeustion的早期版本的上下文,其中例如输入不清描述的空字符串即“”作为为NULL/< NULL>/null,因此它看起来像“”值为NULL。如果他们是NULL这个答案适用。 Sqlfiddle]

错误“所需的输出”

的equip4 1/2在你的“期望的输出”是一个错误,要通过4444 equip1有1/2端口ID 2可以修正之后,期望的输出是你在别处描述的(不清楚)。

NULL port_fnn是没有问题的

空port_fnn不把任何东西到表从查询。 LEFT JOINs永远不会匹配它。

你想要什么行?

你还不清楚。如果非空的source_fnn或dest_fnn没有匹配的port_fn,那么您没有解决的唯一行是。然后在LEFT JOIN输出中,它与NULL port_fnn info配对。

如果您不想要这些行,那将会很奇怪。你不但没有排队进行cust_connection,而且扩展信息的另一半将被扔掉。也许你只会扔掉源和目标都不匹配的行。仍然很奇怪。你必须告诉我们你是否想要这些行。大概你想要他们,因为他们在你的查询。

如果每个source_fnn和dest_fnn都有一个匹配的port_fnn,即有从source_fnn和dest_fnn到port_fnn的外键,那么这绝不会发生,并且您的查询是正确的。

因此,您的查询似乎没问题。

而且它似乎错误地猜测它是无法通过NULL port_fnn来解释为什么它与您错误的预期输出不同。

+0

对不起,如果我不清楚。我已经更新了这个问题。 customer_connections表可以有3个选项。 仅限源FNN。目标FNN或源和目标FNN。这些FNN必须匹配设备FNN的 设备FNN可以是FNN或null。如果设备fnn为空。设备名称不应出现在customer_connection表的空条目中。使用当前查询,它可以。 亲切的问候 奈杰尔 – Nigel 2015-01-21 23:05:41

1

你可以添加一个where条款,如:

where (cc.source_fnn is null or cc.dest_fnn is null) 
     or (src.port_fnn is not null or dst.port_fnn is not null) 

现在它将会始终显示行与空source_fnndest_fnn。当两者都填满后,它将过滤出匹配的port_fnn列为空的行。

因此,您将获得缺少外键的行,但会取消外键引用具有空列的行的行。至少这就是我认为你在寻找的东西。请澄清你的问题,如果不是。

+0

谢谢 - 我试过这个结果相同。 与 '也试过FROM cust_connections立方厘米 LEFT JOIN上cc.source_fnn = src.port_fnn cust_port src和src.port_fnn不为空 LEFT JOIN cust_port DST上cc.dest_fnn = dst.port_fnn和DST。port_fnn不为空' – Nigel 2015-01-21 23:13:01

+0

@Nigel&Andomar对于输入中的NULL:它已经“总是显示具有空的source_fnn或dest_fnn的行”,因为它们位于L JOIN的左侧并且“过滤出匹配的port_fnn列所在的行空“,因为它们在L JOIN和NULL的右侧不能匹配。即查询是正确的。但奈杰尔的“空”意味着*空字符串*!如果有0或1个空的port_fnns,那么我们需要所有的行。否则,如果source_fnn&dest_fnn在非空时充当外键,那么我们可以使用GROUP BY cc.id HAVING src.id <=> MIN(src.id)AND dst.id <=> MIN(dst.id)。 (然后我们根据DRapp的答案填入NULL列。) – philipxy 2015-01-23 11:32:25

1

我认为你正在尝试做的事情可以用IF()对每个相应的源/目标列来完成,以掩饰名称和端口。大多数情况下,人们会尝试做一些事情来阻止空值并显示空字符串等......相反,您需要相反的...如果“port_fnn”为空,您希望隐藏这些元素。

所以我做了每个列的IF(表达式,结果如果为true,结果如果为false)。所以,如果port_fnn为null,则显示空的结果,否则返回无论柱(系统名称,插槽,端口等)

SELECT 
     cc.id AS cc_id, 
     short_name, 
     source_fnn, 
     dest_fnn, 
     service_type,ladder_side, 
     if(src.port_fnn = '', NULL, src.system_name) AS src_system_name, 
     if(src.port_fnn = '', NULL, src.slot_no) AS src_slot_no, 
     if(src.port_fnn = '', NULL, src.port_no) AS src_port_no, 
     if(src.port_fnn = '', NULL, src.port_fnn) AS src_port_fnn, 
     if(dst.port_fnn = '', NULL, dst.system_name) AS dst_system_name, 
     if(dst.port_fnn = '', NULL, dst.slot_no) AS dst_slot_no, 
     if(dst.port_fnn = '', NULL, dst.port_no) AS dst_port_no, 
     if(dst.port_fnn = '', NULL, dst.port_fnn) AS dst_port_fnn 
    FROM 
     cust_connections cc 
      LEFT JOIN cust_port src 
      on cc.source_fnn = src.port_fnn 
      LEFT JOIN cust_port dst 
      on cc.dest_fnn = dst.port_fnn 

我调整上面的查询您的数据工作.. 。NULL与空字符串不同。我将你的表和示例数据复制到SQL Fiddle然后上面的查询。它似乎分别显示源和目标的NULLS。

SQLFiddle per your example structure and data

+0

嗨,你在正确的轨道上我认为... 虽然这个查询没有起作用,但当客户设备为空时它仍然显示设备。声明src.port_ffn中的轻微拼写错误应该是src.port_fnn – Nigel 2015-01-21 23:27:27

+0

@Nigel,修改并创建了表/数据结果的SQLFiddle。 – DRapp 2015-01-22 03:38:43

+0

您的解决方案也有效,但我已经使用了philipxy解决方案,因为它实施起来更简单一些。非常感谢你的输入,非常感谢 – Nigel 2015-01-22 05:40:21