2012-04-24 59 views
6

我有一個不尋常的SQL表(不是我的),它有以下領域(其中包括):last_name, primary_name, secondary_name,表示已婚夫婦。假設姓氏是共享的(不是很現代,我知道),如果它不是一對,那麼primary_namesecondary_name可能是NULL。 (該表還有幾個副本。)我可以讓SQL查詢在每一行上做兩個匹配嗎?

我想要做的是獲取數據庫中所有名稱(「第一個最後」)的列表,按通常方式進行字母順序排列。現在,我通過數據庫使用PHP和PDO做兩遍:

$qstr = "SELECT DISTINCT primary_name, last_name 
      FROM members 
      WHERE primary_name IS NOT null 
      ORDER BY last_name, primary_name"; 
$sth = $dbh->prepare($qstr); 
$sth->execute(); 
// output the results 

$qstr = "SELECT DISTINCT secondary_name, last_name 
      FROM members 
      WHERE secondary_name IS NOT null 
      ORDER BY last_name, secondary_name"; 
$sth = $dbh->prepare($qstr); 
$sth->execute(); 
// output the new results 

但最終的結果是不是按字母順序排序,因爲第二次重新開始。

我怎樣才能一次獲得所有的名字,完全按字母順序排列?有沒有辦法在SQL中做到這一點,或者我需要構建兩個數組,然後在PHP中對它們重新進行字母化?

編輯 數據庫看起來是這樣的:

last_name primary_name secondary_name 
---------------------------------------- 
Abrams  Joe   Susan 
Miller  Sam   Abby 

所需的輸出會是這樣的:

["Joe Abrams","Susan Abrams","Abby Miller","Sam Miller"] 

相反,如果第一遍得到所有的丈夫和第二次通過所有的妻子,我得到這樣的事情:

["Joe Abrams","Sam Miller","Susan Abrams","Abby Miller"] 
+0

你可以發表你想看到的輸出的例子(使用說4或5個不同的名稱組合的例子)? – 2012-04-24 14:27:20

回答

2

另一種方法是使用UNION ...

SELECT 
    * 
FROM 
(
    SELECT primary_name AS pri_sec_name, last_name 
    FROM members 
    WHERE primary_name IS NOT null 

    UNION 

    SELECT secondary_name AS pri_sec_name, last_name 
    FROM members 
    WHERE secondary_name IS NOT null 
) 
    AS data 
ORDER BY 
    last_name, pri_sec_name 

注:UNION(而不是UNION ALL將取消重複結果。

另一種方法是在映射表上進行連接。

SELECT 
    members.last_name, 
    CASE WHEN map.mode = 1 THEN members.primary_name ELSE members.secondary_name END AS pri_sec_name 
FROM 
    members 
INNER JOIN 
    (SELECT 1 as mode UNION ALL SELECT 2 as mode) AS map 
    ON (map.mode = 1 AND members.primary_name IS NOT NULL) 
    OR (map.mode = 2 AND members.secondary_name IS NOT NULL) 
ORDER BY 
    1, 
    2 
+0

UNION是很久以前由於缺乏使用而忘記的事情之一。這似乎工作,但你能向我解釋查詢中的「AS data」部分嗎? – Blazemonger 2012-04-24 14:52:53

+0

不要緊,SQL的錯誤只是爲我解釋。 – Blazemonger 2012-04-24 14:54:11

+0

@Blazemonger - 它只是將所有東西都包裝到一個子查詢中,然後給這個子查詢一個名字。這通常被稱爲*內聯視圖*,因爲您將您的子查詢視爲視圖。 'SELECT * FROM()AS MyViewName' – MatBailie 2012-04-24 14:54:34

7

如果我理解正確的話,我認爲你正在尋找的東西是這樣的:

select distinct coalesce(primary_name, secondary_name) as pri_sec_name, 
    last_name 
from members 
where coalesce(primary_name, secondary_name) is not null 
order by last_name, 
    coalesce(primary_name, secondary_name) 

更新

這聽起來像在某些情況下,你有一個排的姓氏,其中兩個PRIMARY_NAME和secondary_name被填充。下面的查詢應該給你你想要的輸出(抱歉,沒有COALESCE這個時間):

select last_name, pri_sec_name 
from (
    select primary_name as pri_sec_name, last_name from members where primary_name is not null 
    union all 
    select secondary_name as pri_sec_name, last_name from members where secondary_name is not null 
) a 
order by last_name, pri_sec_name 
+1

+1解密。 – 2012-04-24 14:29:17

+0

+1我愛合併! – 2012-04-24 14:31:21

+0

我第一次聽說過'coalesce'。這個SQL的輸出是什麼?在我看來,對於每一個錶行,我仍然得到一個結果行,當(大多數情況下)我需要每個錶行的兩個結果行。 – Blazemonger 2012-04-24 14:33:56

2

我想你需要:

SELECT primary_name AS name 
    , last_name 
    FROM members 
    WHERE primary_name IS NOT NULL 
UNION 
SELECT secondary_name 
    , last_name 
    FROM members 
    WHERE secondary_name IS NOT NULL 
ORDER BY last_name, name 

另一個重寫使用UNION ALL

SELECT COALESCE(primary_name, secondary_name) AS name 
    , last_name 
    FROM members 
UNION ALL 
SELECT secondary_name 
    , last_name 
    FROM members 
    WHERE primary_name IS NOT NULL 
    AND secondary_name IS NOT NULL 
ORDER BY last_name, name 

第2版可能會更快,但它可能會顯示重複的結果。如果有更多的例子,你有這些行,一個Joe Jackson結婚Susan和一個結婚Lea

last_name primary_name secondary_name 
---------------------------------------- 
Jackson Joe   Susan 
Jackson Joe   Lea 

第一個查詢qould顯示:

name last_name 
----------------- 
Joe Jackson 
Lea Jackson 
Susan Jackson 

而第二個將有「重複」:

name last_name 
----------------- 
Joe Jackson 
Joe Jackson 
Lea Jackson 
Susan Jackson 

哪個更合適,取決於您的規格。

相關問題