加入沒有重複行/空值的表
所以我有多個表,我必須在查詢時合併,但兩者
join
似乎union
都沒有實現我的對像是什麼聯盟:
mysql> SELECT NAME, currentstatus, NULL AS username, NULL AS status FROM statustable WHERE Name like '%ahsan%' UNION ALL SELECT NULL AS NAME, NULL AS currentstatus, username, status from awsaccount WHERE username like '%ahsan%'; +--------------+-------------------+----------+--------------------------------+ | NAME | currentstatus | status | username | +--------------+-------------------+----------+--------------------------------+ | Ahsan Naseem | activated | NULL | NULL | | NULL | NULL | ACTIVE | ahsan.naseem | | NULL | NULL | INACTIVE | ahsantest | | NULL | NULL | ACTIVE | ahsantest2 | | NULL | NULL | ACTIVE | ahsantestuserprofileupdate | | NULL | NULL | INACTIVE | ahsantestuserprofileupdate_cli | | NULL | NULL | INACTIVE | decent.ahsan | | NULL | NULL | INACTIVE | decent.ahsan_cli | +--------------+-------------------+----------+--------------------------------+ 8 rows in set (0.00 sec)
加入:
mysql> select * from ( SELECT * from statustable where Name like '%ahsan%' ) as ab JOIN ( SELECT * from awsaccount where username like '%ahsan%' ) as asb; +--------------+-------------------+--------------------------------+----------+ | Name | currentstatus | username | status | +--------------+-------------------+--------------------------------+----------+ | Ahsan Naseem | activated | ahsan.naseem | ACTIVE | | Ahsan Naseem | activated | ahsantest | INACTIVE | | Ahsan Naseem | activated | ahsantest2 | ACTIVE | | Ahsan Naseem | activated | ahsantestuserprofileupdate | ACTIVE | | Ahsan Naseem | activated | ahsantestuserprofileupdate_cli | INACTIVE | | Ahsan Naseem | activated | decent.ahsan | INACTIVE | | Ahsan Naseem | activated | decent.ahsan_cli | INACTIVE | +--------------+-------------------+--------------------------------+----------+ 7 rows in set (0.00 sec)
我想要實現的是:
+--------------+-------------------+----------+--------------------------------+ | NAME | currentstatus | status | username | +--------------+-------------------+----------+--------------------------------+ | Ahsan Naseem | Active | ACTIVE | ahsan.naseem | | NULL | NULL | INACTIVE | ahsantest | | NULL | NULL | ACTIVE | ahsantest2 | | NULL | NULL | ACTIVE | ahsantestuserprofileupdate | | NULL | NULL | INACTIVE | ahsantestuserprofileupdate_cli | | NULL | NULL | INACTIVE | decent.ahsan | | NULL | NULL | INACTIVE | decent.ahsan_cli | +--------------+-------------------+----------+--------------------------------+
我是 sql 新手,將不勝感激您的意見和建議
首先,我應該注意這基本上是一個格式要求:如果前兩列中的值與前一列中的值相同,則您不想重複它們。如果您在應用程序端擁有比在 SQL Server 上更多的 CPU 能力,那麼如果您允許應用程序處理格式化要求,您將可能獲得更好的性能。
也就是說,有時 SQL Server 有足夠的容量來處理格式化,或者由於某種原因在應用程序端這樣做沒有意義。
以下查詢應該做你想做的事:
SET @PrevName := ''; SET @PrevStatus := ''; SET @RowNum := 0; SELECT Name ,currentstatus ,`status` ,username FROM ( SELECT IF(@PrevName = ab.Name, '', ab.Name) as Name ,IF(@PrevName = ab.Name AND @PrevStatus = ab.currentstatus, '', ab.currentstatus) as currentstatus ,asb.`status` ,asb.username ,@PrevName := ab.Name as ActualName ,@PrevStatus := ab.currentstatus as Act_curstatus ,@RowNum := @RowNum + 1 as RowOrder FROM statustable ab CROSS JOIN awsaccount asb WHERE ( ab.Name LIKE '%ahsan%' AND asb.username LIKE '%ahsan%' ) ORDER BY ActualName, Act_curstatus ) sq ORDER BY RowOrder ;
我通過 db-fiddle.com 對此進行了測試;您可以在此處使用查詢和測試數據。
快速解釋:
我們使用變數來保存前一行的
Name
值currentstatus
。如果Name
不同,我們顯示兩個值;如果Name
相同但currentstatus
已更改,我們將Name
留空但顯示新狀態。如果我們有多個名稱或目前狀態,則建立訂單至關重要;如果我們不對這些進行排序,那麼具有不同名稱的行可能會被交錯,這意味著相同的名稱會重複多次,如下所示:
... Ahsan Naseem | activated | ACTIVE | ahsan.naseem | | INACTIVE | ahsantest Bruce Banner | activated | ACTIVE | mr.green Ahsan Naseem | activated | ACTIVE | ahsantest2 | | ACTIVE | ahsantestuserprofileupdate ...
此外,我們必須保留處理行的順序,否則帶有名稱的行可能不是第一行,如下所示:
... | | INACTIVE | ahsantest | | ACTIVE | ahsantest2 Ahsan Naseem | activated | ACTIVE | ahsan.naseem | | ACTIVE | ahsantestuserprofileupdate ...
因此,我們使用@RowNum 在處理行時對行進行順序編號,並最終按該編號進行排序。(我不確定這是否需要;但是,如果沒有它,我的結果會倒過來,所以我顯然確實需要它!)
我們將查詢放在子查詢中,這樣我們就可以將處理後的順序強製到結果上,因此我們可以省略
Actual_Name
、Act_currentstatus
和RowOrder
列。如果您真的想要
NULL
重複值而不是空字元串,只需將 IF 函式中的空字元串替換為 NULL。正如我假設這是出於顯示目的,空字元串可能是更好的選擇,但您可能有其他原因這樣做。
因此,如果我理解這一點,您希望從兩個表中獲取所有行,並在可能的地方加入它們。
您可以通過在它們之間使用 UNION 進行兩個連接來模擬 MySQL 中的完全外部連接。您只需在一側切換使用 LEFT 並在另一側切換使用 RIGHT。
SELECT * FROM statustable t1 LEFT JOIN awsaccount t2 ON t1.statustable_id = t2.awsaccount_id UNION SELECT * FROM statustable t1 RIGHT JOIN awsaccount t2 ON t1.statustable_id = t2.awsaccount_id;
我重用@RDFozz DB Fiddle 來模擬這個:DB Fiddle