编程语言
首页 > 编程语言> > php-自我加入并仅在一个表/一侧忽略空值

php-自我加入并仅在一个表/一侧忽略空值

作者:互联网

我有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为空,我想排除该行,但是如果任何客户源或目标fnns为空,则显示该行.

我正在做一个左(自)联接,以在源和目标fnn上与设备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,并填充没有关联的fnn的设备.即:01-32D6:no_fnn.

第2行的source_system_name和第5行的dst_system_name会发生相同的问题.

解决方法:

”(空字符串)不为NULL. (哪个sqlfiddle输出为“(null)”.)

在文字中,请勿输入“ NULL”或“< NULL>”或“ null”或“(null)”来引用空字符串,就像您最初在问题中所做的那样.要清楚什么是“”,什么是NULL.

”=”但为NULL<>空值.因此,当相等测试涉及到“”时,您的LEFT JOIN会在cc.source_fnn和src.port_fnn列之间以及在cc.dest_fnn和cust_port port_fnn列之间找到匹配项.但是您不希望LEFT JOIN匹配那些行.

您可以这样说:

>将所有_fnn列声明为可空,即,使用NULL(默认值)而不是NOT NULL,并在您现在使用”(空字符串)的表中使用NULL.然后您的查询将给出正确的答案!
>需要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 <> '';

>在您与之保持连接之前,从cust_port中删除这些行:

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,以表明上述内容提供了正确的结果.与”一起使用的查询会错误地从中生成其他虚假行.

如果要使LEFT JOIN中的NULL显示为输出中的空字符串,则可以对这些列使用IFNULL:

IFNULL(dst.port_fnn,”)AS dst_port_fnn

标签:null,left-join,string,mysql,php
来源: https://codeday.me/bug/20191120/2046927.html