[英]How to do a subquery in 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
但是,我將如何構建一個查詢以包含該項目是否在Google上(使用案例陳述或任何需要的內容)
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
使用條件聚合來確定標題是否在指定的商店中。
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
計算給定標題的所有行后,為其中包含google
的行分配1
。 (否則它們將被指定為null
並且count
忽略空值。)此后, if
檢查count
並對標題進行分類,如果它至少有一個google
商店。
這將為您提供不在谷歌上的版本價格數量和谷歌上的數量。 ( 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,則暗示; 但為了清楚起見,我加入了
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;
我會像下面這樣做
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
語法可能只是稍微關閉,因為我現在無法測試它,但我相信這是你想要的精神。 交叉申請也是一個非常有效的聯接,總是有幫助的!
這可能是上述答案中效率最低的,但以下子查詢可以使用%like%
condition:
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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.