2015-01-21 48 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