2016-06-28 155 views
1

,我有以下數據模型:如何做一個子查詢GROUP_CONCAT

`title` 

- id 
- name 

`version` 

- id 
- name 
- title_id 

`version_price` 

- id 
- version_id 
- store 
- price 

這裏是數據的一個例子:

`title` 

- id=1, name=titanic 
- id=2, name=avatar 

`version` 

- id=1, name="titanic (dubbed in spanish)", title_id=1 
- id=2, name="avatar directors cut", title_id=2 
- id=3, name="avatar theatrical", title_id=2 

`version_price` 

- id=1, version_id=1, store=itunes, price=$4.99 
- id=1, version_id=1, store=google, price=$4.99 
- id=1, version_id=2, store=itunes, price=$5.99 
- id=1, version_id=3, store=itunes, price=$5.99 

我想建立一個查詢,這將使我所有在iTunes上有version_price但在Google上沒有的標題。我將如何做到這一點?以下是我迄今爲止:

select 
    title.id, title.name, group_concat(distinct store order by store) 
from 
    version inner join title on version.title_id=title.id inner join version_price on version_price.version_id=version.id 
group by 
    title_id 

這給了我GROUP_CONCAT這說明我是什麼,我有:

id name group_concat(distinct store order by store) 
1 Titanic Google,iTunes        
2 Avatar iTunes          

但我怎麼構建查詢到包括該項目是否是在谷歌(使用CASE語句,Or的任何需要的)

id name group_concat(distinct store order by store) on_google 
1 Titanic Google,iTunes        true 
2 Avatar iTunes          false 

這將基本上是做了group_concat LIKE '%google%',而不是一個正常的where子句。

下面是當前查詢的SQL撥弄一個鏈接,我有:http://sqlfiddle.com/#!9/e52b53/1/0

+0

'where store <>'google''?除了「不同」的東西外,並不是group_concat的工作是爲你過濾東西。過濾在'where'子句中完成。 –

+0

你期望得到什麼? '1 |泰坦尼克號Google,iTunes'或者只是'1 |泰坦尼克號iTunes'? – Alex

+0

@MarcB請看更新的問題。 – David542

回答

1

使用條件聚合來確定標題是否在指定的商店中。

select title.id, title.name, group_concat(distinct version_price.store order by store), 
if(count(case when store = 'google' then 1 end) >= 1,'true','false') as on_google 
from version 
inner join title on version.title_id=title.id 
inner join version_price on version_price.version_id=version.id 
group by title.id, title.name 

count(case when store = 'google' then 1 end) >= 1計數所有行對於給定標題分配1到在他們google行之後。 (否則他們將被分配null並且count忽略空值。)之後,if檢查count,並且如果標題上至少有一個google存儲,則將其分類。

+0

非常好,這工作得很好,這種方法比我目前的子查詢方法好得多。 – David542

+0

你能否在你的回答中解釋以下內容以及它是如何工作的? 'if(count(store ='google'then 1 end)> = 1,'true','false')作爲on_google'。如何使用與正常情況不同的'if(count(...))'? – David542

+0

補充說明。 –

0

我會做類似下面

SELECT 
    * 
FROM 
    title t 
INNER JOIN 
    version v ON 
     v.title_id = t.id 
CROSS APPLY (
    SELECT 
     * 
    FROM 
     version_price vp 
    WHERE 
     vp.store <> 'google' 
) c ON c.version_id == v.id 

語法可能只是有點過,因爲我不能測試它現在,但我相信這是你想要的精神。交叉申請也是一個非常有效的加入,它總是有幫助的!

+0

我從來沒有聽說過交叉申請。這對mysql有效嗎?另外,你可以在這裏的sqlfiddle上試試看它是否有效:http://sqlfiddle.com/#!9/e52b53/1/0 – David542

+0

給我幾分鐘,我會迴應! – NewDeveloper

+0

在調查之後,我沒有在MySQL中看到任何「Cross Apply」。對於那個很抱歉!我想這個解決方案只適用於MSSQL和SQL。 – NewDeveloper

1

這會給你不是谷歌版本價格的數量,而是谷歌上的數字。 (COUNT不計算空值。)

SELECT t.id, t.name 
    , COUNT(DISTINCT vpNotG.id) > 0 AS onOtherThanGoogle 
    , COUNT(DISTINCT vpG.id) > 0 AS onGoogle 
FROM title AS t 
    INNER JOIN version AS v ON t.id=v.title_id 
    LEFT JOIN version_price AS vpNotG 
     ON v.id=vpNotG.version_id 
     AND vpNotG.store <> 'Google' 
    LEFT JOIN version_price AS vpG 
     ON v.id=vpG.version_id 
     AND vpG.store = 'Google' 
GROUP BY t.id 

或類似VKP的另一個解決方案:

SELECT t.id, t.name 
    , COUNT(DISTINCT CASE WHEN store = 'Google' THEN vp.id ELSE NULL END) AS googlePriceCount 
    , COUNT(DISTINCT CASE WHEN store = 'iTunes' THEN vp.id ELSE NULL END) AS iTunesPriceCount 
    , COUNT(DISTINCT CASE WHEN store <> 'Google' THEN vp.id ELSE NULL END) AS nonGooglePriceCount 
FROM title AS t 
    INNER JOIN version AS v ON t.id = v.title_id 
    INNER JOIN version_price AS vp ON v.id = vp.version_id 
GROUP BY t.id 

注:ELSE NULL可以省略,因爲如果沒有提供ELSE它被暗示;但爲了清楚起見,我包括在內

+0

嘗試此查詢時出現錯誤。 – David542

+0

@ David542我剛剛編輯它,我有一些id字段顛倒。 – Uueerdo

+0

第二種解決方案效果很好。第一個我仍然有一些問題運行查詢。 – David542

0

這可能是最沒有效率的上述答案的,但下面的子查詢會的工作,使用%like%條件:

select *, case when stores like '%google%' then 1 else 0 end on_google 
from (select title.id, title.name, group_concat(distinct store order by store) stores 
from version inner join title on version.title_id=title.id inner join version_price 
on version_price.version_id=version.id group by title_id) x 

id name stores on_google 
1 Titanic Google,iTunes 1 
2 Avatar iTunes 0 
1

http://sqlfiddle.com/#!9/b8706/2

你可以:

SELECT 
    title.id, 
    title.name, 
    group_concat(distinct version_price.store), 
    MAX(IF(version_price.store='google',1,0)) on_google 
FROM version 
INNER JOIN title 
ON version.title_id=title.id 
INNER JOIN version_price 
ON version_price.version_id=version.id 
GROUP BY title_id; 

並在需要過濾的記錄中添加HAVING到查詢:

SELECT 
    title.id, 
    title.name, 
    group_concat(distinct version_price.store), 
    MAX(IF(version_price.store='google',1,0)) on_google 
FROM version 
INNER JOIN title 
ON version.title_id=title.id 
INNER JOIN version_price 
ON version_price.version_id=version.id 
GROUP BY title_id 
HAVING on_google;