2015-07-21 70 views
0

我有一個客戶表和一個存儲客戶地址的單獨表。它們通常在地址表中至少有兩個連接記錄,如果不是更多。當我想要一個郵件列表時,我需要客戶的帳單地址,在地址表中用'type'列標記。不幸的是,並非每個客戶都有一個標有'結算'的地址。我怎麼能寫一個陳述來選擇標記賬單的地址,除非沒有一個,在這種情況下選擇另一個。我不想只用'或',因爲我只想要選擇一個記錄。MySQL加入從一系列條件中只選擇了1個條件

爲了簡便起見,表看起來是這樣的:

客戶:
ID

地址:
ID
客戶ID
型(發貨,開票, '',等)

下面是一些SQL是不是我想要的(笑): 從客戶選擇*內部聯接地址上address.custid = Customer.id其中Address.type =「結算」

!!後加! !
Kevin提供了我非常喜歡的coalesce解決方案,但它僅適用於地址表中的單個列。我需要從表格中的所有字段/列形成一個可用的地址。

我一直在試圖做到這一點,像這樣(只使用兩個字段這裏簡單):
select coalesce(concat_ws(',',a1.address, a1.city), concat_ws(',',a2.address, a2.city), concat_ws(',',a3.address, a3.city)) from customer c ...
然而,CONCAT_WS打破總是返回非空的聚結。
我也嘗試只是在做每場獨立凝聚:
coalesce(a1.address, a2.address), coalesce(a1.address2, a2.address2), etc
但這的地址來自3條不同的記錄,例如,如果地址2(用於房間號或其他)「混淆」效果空了一排,然後它會在那裏插入一條不同的記錄地址2。

有誰知道如何防止concat_ws返回非null,即使字段爲空內?

回答

1

如果存在的話這將讓你的賬單地址,否則送貨地址:

select ifnull(a1.address, a2.address) from customer c 
left join address a1 on c.id = a1.custid and a1.type = 'billing' 
left join address a2 on c.id = a2.custid and a2.type = 'shipping' 

,如果你想檢查是否有其他類型,可以添加連接和使用,而不是IFNULL聚結,像這樣:

select coalesce(a1.address, a2.address, a3.address) from customer c 
left join address a1 on c.id = a1.custid and a1.type = 'billing' 
left join address a2 on c.id = a2.custid and a2.type = 'shipping' 
left join address a3 on c.id = a3.custid and a3.type = 'X' 
+0

再加一個包含''''類型的條件? –

+0

列出的每個答案都很棒,但我認爲這是我最喜歡的答案,主要是由於沒有使用聯盟(我也沒有想到)。我從來沒有見過coalesce功能。我會試試看,如果有效,我會回來給你檢查。非常感謝每個人爲您的出色投入 - Kevin,VKP,shawnt00,Ben Kulka。 – Todd

+0

@Kevin好的,如果我只想從地址表中找到單個字段,那麼coalesce解決方案效果很好。但是,我需要他們。謹慎嘗試擴展這一點?我一直在試圖這樣做(爲簡單起見,在這裏只使用兩個字段): 'select coalesce(concat_ws(',',a1.address,a1.city),concat_ws(',',a2.address, a2.city),concat_ws(',',a3.address,a3.city)from customer c ...'然而,concat_ws通過總是返回非空來打破coalesce。 – Todd

2
select c.id, a.id 
from customer c join address a on a.custid = c.id 
where a.type = 'Billing' 
union 
select c.id, a.id 
from customer c join address a on a.custid = c.id 
where a.type <> 'Billing' 
and c.id not in (select custid from address a where a.type = 'Billing') 

這是一種方法。

+0

增加一個條件,第二個查詢'那裏c.id不在(選擇地址客戶ID其中type =「結算」)工會的' –

+0

下半年仍然可以爲每個客戶返回多個地址。 – shawnt00

0

沒有OR子句就很難做到這一點。假設你正在尋找的地址ID:

SELECT 
Address.id 
FROM Address LEFT JOIN Customer ON Customer.id = Address.custid 
WHERE Address.id EXIST (
    SELECT 
    Address.id 
    FROM Address LEFT JOIN Customer ON Customer.id = Address.custid 
    WHERE Address.type LIKE 'shipping' 
) OR Address.type = 'billing' 
0
select ... 
from customer c join address a on a.custid = c.id 
where a.type = 'Shipping' 
union all 
select ... 
from customer c join address a on a.custid = c.id 
where a.type = 'Billing' and not exists (
    select 1 from address a2 
    where a2.custid = a.custid and a2.type = 'Shipping' 
) 

如果你需要一點點更通用的牛逼母雞,你可能會發現這個「黑客」有用:

select * from address 
where id in (
    select 
     min(case type 
      when 'Shipping' then 100000000 
      when 'Billing' then 200000000 
      when ...  then 300000000 
      else 900000000 
     end + a.id) % 100000000 /* not sure of MySQL for modulo operation */ 
    from address a 
    group by custid 
)