2014-11-03 40 views
0

我有以下查詢:MySQL的 - 有條件加入了列

select ad_st_id_state, count(distinct id_visit) as Visits 
from sf_visit 
join vr_users on vi_us_id_user = sus_us_id_user 
join sf_pdv on vi_pdv_id_pdv = id_pdv 
join sf_address on pdv_ad_id_address = id_address 

group by ad_st_id_state 
order by ad_st_id_state 

,我也有這樣的一個:

正如你所看到的查詢是幾乎除了同一個額外的join聲明。 兩個查詢返回我,我需要正確的價值觀,但我需要他們一起在一個單一的表,所以我這樣做:

select fffuuu.ad_st_id_state, count(distinct id_visit) as Visitas, fffuuu.doneVisits 
from sf_visit 
join vr_users on vi_us_id_user = sus_us_id_user 
join sf_pdv on vi_pdv_id_pdv = id_pdv 
join sf_address on pdv_ad_id_address = id_address 

join (
select ad_st_id_state, count(distinct id_visit) as doneVisits 
from sf_visit 
join vr_users on vi_us_id_user = sus_us_id_user 
join sf_pdv on vi_pdv_id_pdv = id_pdv 
join sf_address on pdv_ad_id_address = id_address 
join sf_visit_file_time on id_visit = vft_vi_id_visit 

group by ad_st_id_state 
order by ad_st_id_state 
) as fffuuu on sf_address.ad_st_id_state = fffuuu.ad_st_id_state 

group by ad_st_id_state 
order by ad_st_id_state 

或者換句話說,我加入了第一個查詢與第二個作爲子查詢。結果集很好而且正確,但花費的時間太長,所以我在這個查詢正在運行的另一個系統中出現超時。 每個查詢獨立運行速度快,但加入他們是太慢我的需求...

我想知道是否有一種方法來優化這個,我想如果有一些聯合條件語句或某事。我搜索了信息,但我沒有任何運氣。 我在想像這樣的東西:

select ad_st_id_state, count(distinct id_visit) as Visits, if(@someVariable := true) as DoneVisits 
from sf_visit 
join vr_users on vi_us_id_user = sus_us_id_user 
join sf_pdv on vi_pdv_id_pdv = id_pdv 
join sf_address on pdv_ad_id_address = id_address 
if (@someVariable == true) then join sf_visit_file_time on id_visit = vft_vi_id_visit 

group by ad_st_id_state 
order by ad_st_id_state 

或類似的東西。請問一些身體可以幫我嗎?我怎樣才能優化這個? 感謝

+0

在T-SQL下工作,是使我確定這將在MySQL工作太添加加入像....上id_visis = vft_vi_id_visit和@someVariable = 1個 – SkelDave 2014-11-03 19:59:21

+0

@SkelDave JOIN sf_visit_file_time我想你的建議,但我不知道該怎麼做,因爲我在MySQL中遇到了語法錯誤。我只是編寫了關於someVariable的代碼來闡明我想要做的事情。 – Metafaniel 2014-11-03 20:07:14

回答

4

你可以使用一個外部連接來計算sf_visit_file_time和一個case語句嗎?很明顯,我沒有本地模式,但類似於:

select ad_st_id_state, 
    count(distinct id_visit) as Visits, 
    count(distinct case when vft_vi_id_visit is not null then id_visit end) as DoneVisits 
from sf_visit 
join vr_users on vi_us_id_user = sus_us_id_user 
join sf_pdv on vi_pdv_id_pdv = id_pdv 
join sf_address on pdv_ad_id_address = id_address 
left join sf_visit_file_time on id_visit = vft_vi_id_visit 
group by ad_st_id_state 
order by ad_st_id_state 
+0

戈登就夠了。在我的示例中,第一個計數獲取的訪問次數未完成,而不是所有訪問次數。在第二個中,我添加了0,因爲我擔心在mysql中爲null添加null,我沒有一個實例方便地檢查它的作用。我從你的回答中假設,它增加了一個0? – 2014-11-03 20:11:09

+0

戈登,根據您的反饋回答編輯。 – 2014-11-03 20:13:44

+0

嘿,你們都做到了!這個答案也適用,它更短,更清晰!在選擇最好的答案之前,我想給每個答案都給予適當的閱讀,但我非常喜歡這個答案。非常感謝你的努力! – Metafaniel 2014-11-03 20:52:38

1

如果這兩個查詢是速度快,很好地工作,你只需要在一個表中的結果,你可以使用一個聯盟選擇http://dev.mysql.com/doc/refman/5.0/en/union.html

select ad_st_id_state, count(distinct id_visit) as Visits, '' as DoneVisits 
from sf_visit 
join vr_users on vi_us_id_user = sus_us_id_user 
join sf_pdv on vi_pdv_id_pdv = id_pdv 
join sf_address on pdv_ad_id_address = id_address 
group by ad_st_id_state 
UNION 
select ad_st_id_state, '' as Visits, count(distinct id_visit) as DoneVisits 
from sf_visit 
join vr_users on vi_us_id_user = sus_us_id_user 
join sf_pdv on vi_pdv_id_pdv = id_pdv 
join sf_address on pdv_ad_id_address = id_address 
join sf_visit_file_time on id_visit = vft_vi_id_visit /* Another join has been added */ 
group by ad_st_id_state 
order by ad_st_id_state 
+0

我試過了,但是我得到了一個錯誤代碼:1221.UNION和ORDER BY的用法不正確可能我對'union' = P不太瞭解我很少使用它。你能請進一步解釋我嗎?我只是在括號中加入每個查詢並添加'union' = P – Metafaniel 2014-11-03 19:57:25

+0

@Metafaniel爲您添加了一個樣本。我假設你想區分訪問和完成訪問者。 – SLin 2014-11-03 20:05:54

+0

感謝這似乎是有用的,我理解'union'更好的這個例子,但是,而不是數字,我在我的結果集中有'BLOB'標誌。任何想法爲什麼?再次感謝 – Metafaniel 2014-11-03 20:10:37

0

在這種情況下,你是「有條件加入」被告訴你「如果我在另一張表中找到記錄,這意味着訪問完成。」

爲了創造「條件」您可以使用LEFT OUTER JOIN,而不是一個INNER JOIN

OUTER JOIN,而不是一個INNER JOIN如果記錄在表中找到,而不是其他不破。它仍然會返回記錄。有LEFTRIGHT外連接。你應該自己研究它們。但基本上,以達到你想要什麼,你可以做這樣的事情:

select ad_st_id_state, count(distinct vft_vi_id_visit) as DoneVisits 
from sf_visit 
join vr_users on vi_us_id_user = sus_us_id_user 
join sf_pdv on vi_pdv_id_pdv = id_pdv 
join sf_address on pdv_ad_id_address = id_address 
left outer join sf_visit_file_time on id_visit = vft_vi_id_visit /* Another join has been added */ 
group by ad_st_id_state 
order by ad_st_id_state 

所以,現在,DoneVisits將永遠存在 - 它只是爲零時,有沒有sf_visit_file_time記錄它。

+0

我理解你的觀點,但在這種情況下,'left outer join'會返回Visits值,'inner join'會返回DoneVisits值,但我需要在一個結果集中使用這兩個值。感謝您的回答 – Metafaniel 2014-11-04 15:39:40

+0

這就是要做的。我現在看到'id_visit'是計算DISTINCT的錯誤列。它應該是'vft_vi_id_visit'。我相應地更新了我的答案。儘管如此,所描述的概念正是您所需要的,正如您接受的答案所表明的那樣。 – 2014-11-04 17:41:40

1

這兩個查詢都乾淨而高效。所以,只需將它們連接在一起進行演示,將它們當作子查詢處理。

SELECT a.ad_st_id_state, a.Visits, b.DoneVisits 
    FROM (
     /* put your first query here */ 
     ) AS a 
    LEFT JOIN (
     /* put your second query here */ 
     ) AS b ON a.ad_st_id_state = b.ad_st_id_state 
ORDER BY a.ad_st_id_state 

這使得一個更大的查詢,但它應該在你有兩個查詢的時間之和運行。您可以將ORDER BY子句保留在子查詢中。

因此,它看起來像這樣......一個真正的查詢俱樂部三明治。

SELECT a.ad_st_id_state, a.Visits, b.DoneVisits 
    FROM (
      select ad_st_id_state, count(distinct id_visit) as Visits 
      from sf_visit 
      join vr_users on vi_us_id_user = sus_us_id_user 
      join sf_pdv on vi_pdv_id_pdv = id_pdv 
      join sf_address on pdv_ad_id_address = id_address 
      group by ad_st_id_state 
     ) AS a 
    LEFT JOIN (
      select ad_st_id_state, count(distinct id_visit) as DoneVisits 
      from sf_visit 
      join vr_users on vi_us_id_user = sus_us_id_user 
      join sf_pdv on vi_pdv_id_pdv = id_pdv 
      join sf_address on pdv_ad_id_address = id_address 
      join sf_visit_file_time on id_visit = vft_vi_id_visit /* Another join */ 
      group by ad_st_id_state 
     ) AS b ON a.ad_st_id_state = b.ad_st_id_state 
ORDER BY a.ad_st_id_state 
+0

我已經設法遵循你的答案,我已經得到了期望的結果!而且比我想要做的要快得多。你說得對,我只需要一個三明治就可以了。我試圖找出其他答案,但可能這個答案就是答案。謝謝 – Metafaniel 2014-11-03 20:22:45