[英]SQL inner join many to many instances existance
我有兩張桌子
Campaigns ( name, date, url, etc. )
campaign_tags ( campaign_name, tag )
我正在嘗試選擇所有具有標簽列表的廣告系列,即
SELECT *
from campaigns
inner join campaign_tags on campaigns.name=campaign_tags.name
where ( list of campaign tags ) in ( list of tags )
我有標簽列表(它們是用“,”分隔的字符串),我想要在列表中包含所有標簽的廣告系列。 我怎樣才能做到這一點?
編輯; 樣本數據:
Campaign:
"MyCampaign", "22/11/2017","https://stackoverflow.com/posts/47431394"
"MyCampaign2", "22/11/2017","https://stackoverflow.com/posts/47431394"
CampaignTags: "MyCampaign","sports" "MyCampaign","stackoverflow" "MyCampaign","Life" "MyCampaign2","food"
如果要查詢的列表是"sports","life",stackoverflow","health","programming"
,則應該出現” MyCampaign“,” 22/11/2017“等,因為它的所有標簽都是包括在列表中,但不應該包含“ MyCampaign2”;如果我要查詢"food","sports"
,則應該顯示“ MyCampaign2”,如果我要查詢“ sports”,則應該不顯示任何內容。
這樣一來,那些擁有這些標簽的廣告系列將不再是單個標簽,而是所有這些標簽
SELECT c.*
FROM campaigns c
INNER JOIN campaign_tags ct ON c.name=ct.name
WHERE ct.tag IN ( "sports","life" )
GROUP BY c.name
HAVING COUNT(DISTINCT ct.tag) = SUM(ct.tag IN ( "sports","life" ))
作為變體
SELECT *
FROM Campaigns
WHERE name IN(
SELECT campaign_name
FROM campaign_tags
WHERE tag IN("sports","life")
GROUP BY campaign_name
HAVING COUNT(tag)=LENGTH('"sports","life"')-LENGTH(REPLACE('"sports","life"',',',''))+1 -- count of tags
)
SQL小提琴- http://sqlfiddle.com/#!9/8870c/10
新條件的第二個變體
SELECT *
FROM Campaigns
WHERE name IN(
SELECT campaign_name
FROM campaign_tags
GROUP BY campaign_name
HAVING
COUNT(CASE
WHEN tag IN("sports","life","stackoverflow","health","programming")
THEN tag
END)=COUNT(tag)
)
SQL小提琴- http://sqlfiddle.com/#!9/ed1294/12
如果標簽可以在表格中復制,也可以使用DISTINCT
SELECT *
FROM Campaigns
WHERE name IN(
SELECT campaign_name
FROM campaign_tags
GROUP BY campaign_name
HAVING
COUNT(DISTINCT CASE
WHEN tag IN("sports","life","stackoverflow","health","programming")
THEN tag
END)=COUNT(DISTINCT tag)
)
抱歉,此解決方案僅適用於sqlserver,未能看到它適用於mysql。 但會因為對其他人有用而離開。 Charindex可以用Locate函數代替,但是mysql不支持WITH
該解決方案查找在搜索字符串中具有所有標簽的所有廣告系列
該解決方案很容易實現您希望搜索的價值。
唯一需要注意的是,任何標簽都不能包含“,”。 如果可能發生這種情況,則需要另一個定界符。 。 也不會在搜索字符串中容納重復的標簽。
作為記錄,使用campaign_id會更好地進行聯接
create table c
(
thename varchar(100),
thedate datetime,
theurl varchar(100)
)
create table ctags
(
thename varchar(100),
thetag varchar(100)
)
create unique index c_u1 on c(thename)
create unique index ctags_u1 on ctags(thename,thetag)
insert into c values ('mycampaign_good1','20170101','http://127.0.0.1')
insert into c values ('mycampaign_bad1','20170101','http://127.0.0.1')
insert into ctags values ('mycampaign_good1','sports')
insert into ctags values ('mycampaign_good1','stackoverflow')
insert into ctags values ('mycampaign_good1','programming')
insert into ctags values ('mycampaign_bad1','sports')
insert into ctags values ('mycampaign_bad1','stackoverflow')
insert into ctags values ('mycampaign_bad1','life')
/* only good1 succeeds*/
with searchstr as
(
select 'programming,sports,stackoverflow' str
),
numvals as
(
select len(searchstr.str) - len(replace(searchstr.str,',',''))+1 n
from searchstr
)
select c.thename
from c join ctags on c.thename = ctags.thename
where charindex (','+ctags.thetag,','+(select str from searchstr)) >0
group by c.thename
having count(*) = (select numvals.n from numvals)
;
/* both succeed */
with searchstr as
(
select 'sports,stackoverflow' str
),
numvals as
(
select len(searchstr.str) - len(replace(searchstr.str,',',''))+1 n
from searchstr
)
select c.thename
from c join ctags on c.thename = ctags.thename
where charindex (','+ctags.thetag,','+(select str from searchstr)) >0
group by c.thename
having count(*) = (select numvals.n from numvals)
;
/* both fail as neither have friends */
with searchstr as
(
select 'friends,sports,stackoverflow' str
),
numvals as
(
select len(searchstr.str) - len(replace(searchstr.str,',',''))+1 n
from searchstr
)
select c.thename
from c join ctags on c.thename = ctags.thename
where charindex (','+ctags.thetag,','+(select str from searchstr)) >0
group by c.thename
having count(*) = (select numvals.n from numvals)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.