我有以下数据模型:
`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
答案 0 :(得分: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
{{1}} 1}}存储在它上面。
答案 1 :(得分: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,则暗示;但为了清楚起见,我加入了。
答案 2 :(得分: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;
答案 3 :(得分: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
语法可能只是一点点,因为我现在无法测试它,但我相信这是你想要的精神。交叉申请也是一种非常有效的联接,总是有用的!
答案 4 :(得分: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