[英]One to many join with three tables
I have a tables: sites, campaigns, and out
for a campaign tracking system I am building. 我有一个表:网站,广告活动,并
out
了运动追踪系统我建立。 When a link is clicked the out table gets its hits updated where the site id and campaign id match. 单击链接后,out表将在网站ID和广告系列ID匹配的位置更新匹配。
In the out table there is a campaign_id and a site_id which both correspond to the sites and campaigns tables respectivly. 在out表中,有一个campaign_id和site_id,它们分别对应于sites和campaigns表。 To complicate things more, each site can has 4 campaigns (campaign_a, campaign_b, campaign_id_reviews, campaign_id_reviews_phone).
更复杂的是,每个站点可以有4个广告系列(campaign_a,campaign_b,campaign_id_reviews,campaign_id_reviews_phone)。 I want to JOIN the three tables and for each site I want the folllowing to be on one line:
我想加入三个表,对于每个站点,我希望将其放在一行上:
site.site_name, site.campaign_id_a, campaigns.campaign_name, out.hits,
site.campaign_id_b, campaigns.campaign_name, out.hits,
site.campaign_id_reviews, campaigns.campaign_name, out.hits,
site.campaign_id_reviews_phone, campaigns.campaign_name, out.hits
Here is my attempt which does not bring all the site_id/campaign_id combinations back, it only brings back one record for each site_id and not all site_id/campaign_id combinations 这是我的尝试,它没有带回所有site_id / campaign_id组合,它仅为每个site_id带回一条记录,而不是所有site_id / campaign_id组合
SELECT s.*, c.*, o.* FROM sites s
INNER JOIN campaigns c ON s.campaign_id_a=c.campaign_id
INNER JOIN campaigns ON s.campaign_id_b=campaigns.campaign_id
INNER JOIN `out` o ON s.campaign_id_a=o.campaign_id AND s.site_id=o.site_id
WHERE s.site_id NOT IN(100,101)
ORDER BY o.site_id ASC
My Create table with 3 record dump: 我的具有3条记录转储的Create表:
CREATE TABLE IF NOT EXISTS `sites` (
`site_id` mediumint(4) NOT NULL AUTO_INCREMENT,
`site_name` varchar(70) NOT NULL,
`campaign_id_a` tinyint(4) NOT NULL,
`campaign_id_b` tinyint(4) NOT NULL,
`a_display_name` varchar(50) NOT NULL,
`b_display_name` varchar(50) NOT NULL,
`campaign_id_reviews` tinyint(4) NOT NULL,
`campaign_id_reviews_phone` tinyint(3) NOT NULL DEFAULT '4',
PRIMARY KEY (`site_id`),
UNIQUE KEY `site_id` (`site_id`),
UNIQUE KEY `site_name` (`site_name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=102 ;
INSERT INTO `sites` (`site_id`, `site_name`, `campaign_id_a`, `campaign_id_b`, `a_display_name`, `b_display_name`, `campaign_id_reviews`, `campaign_id_reviews_phone`) VALUES
(1, 'example.com', 1, 8, 'hard456', 'easy123', 3, 4),
(2, 'example.org', 1, 8, 'hard456', 'easy123', 3, 4),
(3, 'example.net', 8, 8, 'easy123', 'easy123', 3, 4);
CREATE TABLE IF NOT EXISTS `out` (
`out_id` mediumint(7) NOT NULL AUTO_INCREMENT,
`site_id` tinyint(4) NOT NULL,
`campaign_id` tinyint(4) NOT NULL DEFAULT '0',
`hits` int(11) NOT NULL,
`date_last_hit` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`out_id`),
UNIQUE KEY `site2campaign` (`site_id`,`campaign_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=101 ;
INSERT INTO `out` (`out_id`, `site_id`, `campaign_id`, `hits`, `date_last_hit`) VALUES
(19, 60, 3, 418, '2015-11-16 22:52:33'),
(10, 2, 1, 1135, '2015-11-15 04:51:32'),
(20, 60, 1, 1710, '2015-11-14 13:52:20');
CREATE TABLE IF NOT EXISTS `campaigns` (
`campaign_id` tinyint(4) NOT NULL AUTO_INCREMENT,
`campaign_name` varchar(60) NOT NULL,
`network` varchar(60) NOT NULL,
`url` varchar(400) NOT NULL,
PRIMARY KEY (`campaign_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=10 ;
INSERT INTO `campaigns` (`campaign_id`, `campaign_name`, `network`, `url`) VALUES
(1, 'Hard456', 'Hard Network', 'exampleURL'),
(3, 'medium678', 'Medium Network', 'examplewithURL'),
(8, 'easy123', 'Easy Network', 'exampleURLLoaction');
(4, 'none23', 'None Network', 'urlExample');
The problem is you are overwriting columns names. 问题是您要覆盖列名。 Although I have not tested it this should work.
尽管我还没有测试过,但这应该可行。 You can work on a similar pattern to get the out.hits for each campaign id.
您可以使用类似的模式来获取每个广告系列ID的out.hits。
SELECT
r3.*, c4.campaign_name c_name_rev_phone
FROM
(SELECT
r2.*, c3.campaign_name c_name_rev
FROM
(SELECT
r1.*, c2.campaign_name c_name_b
FROM
(SELECT
s1.site_id s_id,
s1.site_name sname,
s1.campaign_id_a c_id_a,
s1.campaign_id_b c_id_b,
s1.campaign_id_reviews c_id_rev,
s1.campaign_id_reviews_phone c_id_rev_phone,
c1.campaign_name c_name_a
FROM sites s1 JOIN campaigns c1 ON s1.campaign_id_a = c1.campaign_id ) r1
JOIN campaigns c2 ON c2.campaign_id=r1.c_id_b ) r2
JOIN campaigns c3 ON c3.campaign_id=r2.c_id_rev ) r3
JOIN campaigns c4 on c4.campaign_id=r3.c_id_rev_phone;
Edit 1- 编辑1-
As per the sample data provided in the question the result of the following query would be 根据问题中提供的样本数据,以下查询的结果将是
SELECT s.*, c.* FROM sites s
INNER JOIN campaigns c ON s.campaign_id_a=c.campaign_id
INNER JOIN campaigns ON s.campaign_id_b=campaigns.campaign_id
WHERE s.site_id NOT IN(100,101);
Result: 结果:
site_id |site_name |campaign_id_a |campaign_id_b |a_display_name |b_display_name |campaign_id_reviews |campaign_id_reviews_phone |campaign_id |campaign_name |network |url
--------|---------------|---------------|---------------|---------------|---------------|-----------------------|---------------------------|---------------|---------------|---------------|------------------
1 |example.com |1 |8 |hard456 |easy123 |3 |4 |1 |Hard456 |Hard Network |exampleURL
2 |example.org |1 |8 |hard456 |easy123 |3 |4 |1 |Hard456 |Hard Network |exampleURL
3 |example.net |8 |8 |easy123 |easy123 |3 |4 |8 |easy123 |Easy Network |exampleURLLoaction
Result of query in answer: 答案查询结果:
s_id |sname |c_id_a |c_id_b |c_id_rev |c_id_rev_phone |c_name_a |c_name_b |c_name_rev |c_name_rev_phone
------------------------|-------|-------|-----------|---------------|-----------|-----------|-----------|----------------
1 |example.com |1 |8 |3 |4 |Hard456 |easy123 |medium678 |none23
2 |example.org |1 |8 |3 |4 |Hard456 |easy123 |medium678 |none23
3 |example.net |8 |8 |3 |4 |easy123 |easy123 |medium678 |none23
Notice how campaign names for campaign_id_a
, campaign_id_b
, campaign_id_reviews
etc are individually fetched. 请注意,如何分别获取
campaign_id_a
, campaign_id_b
, campaign_id_reviews
等的广告系列名称。
Here is the query that would give you the complete answer: 这是可以为您提供完整答案的查询:
SELECT
r3.*,
c4.campaign_name c_name_rev_phone,
o4.hits hits_rev_phone
FROM
(SELECT
r2.*,
c3.campaign_name c_name_rev,
o3.hits hits_rev
FROM
(SELECT
r1.*,
c2.campaign_name c_name_b,
o2.hits hits_b
FROM
(SELECT
s1.site_id s_id,
s1.site_name sname,
s1.campaign_id_a c_id_a,
s1.campaign_id_b c_id_b,
s1.campaign_id_reviews c_id_rev,
s1.campaign_id_reviews_phone c_id_rev_phone,
c1.campaign_name c_name_a,
o1.hits hits_a
FROM sites s1 JOIN campaigns c1 ON s1.campaign_id_a = c1.campaign_id JOIN `out` o1 ON (c1.campaign_id=o1.campaign_id AND o1.site_id=s1.site_id)) r1
JOIN campaigns c2 ON c2.campaign_id=r1.c_id_b JOIN `out` o2 ON (c2.campaign_id=o2.campaign_id AND o2.site_id=r1.s_id)) r2
JOIN campaigns c3 ON c3.campaign_id=r2.c_id_rev JOIN `out` o3 ON (c3.campaign_id=o3.campaign_id AND o3.site_id=r2.s_id)) r3
JOIN campaigns c4 on c4.campaign_id=r3.c_id_rev_phone JOIN `out` o4 ON (c4.campaign_id=o4.campaign_id AND o4.site_id=r3.s_id);
This would give an empty result for the sample data set your have provided because a lot of campaign_id
, site_id
combinations are not present in table out
. 这将为您提供的示例数据集提供空白结果,因为表
out
中不存在很多campaign_id
和site_id
组合。 Since we are doing an INNER
join you would lose out on this information. 由于我们正在进行内部
INNER
您将失去这些信息。 If you want hits
to be reported as 0
when site_id
, campaign_id
combination is not present then you need to use a LEFT JOIN
. 如果您希望在
site_id
, campaign_id
组合不存在时将hits
报告为0
,则需要使用LEFT JOIN
。
Feel free to revert if this is not what you want. 如果这不是您想要的,请随时还原。
You appear to join against campaigns twice, but only ever return anything that matches on compaign_id_a. 您似乎两次参加了竞选活动,但只返回了与compaign_id_a相匹配的任何内容。 Campaign_id_b is ignored in the results while the other 2 campaign ids are not processed at all.
结果中会忽略Campaign_id_b,而其他两个广告系列ID都不会处理。
Splitting it up to get each campaign id and union the results together:- 将其拆分以获取每个广告系列ID,并将结果合并在一起:-
(SELECT s.site_id,
s.site_name,
s.campaign_id_a,
s.campaign_id_b,
s.a_display_name,
s.b_display_name,
s.campaign_id_reviews,
s.campaign_id_reviews_phone,
o.out_id,
o.hits,
o.date_last_hit,
c.campaign_id,
c.campaign_name,
c.network,
c.url
FROM sites s
INNER JOIN campaigns c ON s.campaign_id_a = c.campaign_id
INNER JOIN `out` o ON c.campaign_id = o.campaign_id AND s.site_id = o.site_id
WHERE s.site_id NOT IN (100,101))
UNION
(SELECT s.site_id,
s.site_name,
s.campaign_id_a,
s.campaign_id_b,
s.a_display_name,
s.b_display_name,
s.campaign_id_reviews,
s.campaign_id_reviews_phone,
o.out_id,
o.hits,
o.date_last_hit,
c.campaign_id,
c.campaign_name,
c.network,
c.url
FROM sites s
INNER JOIN campaigns c ON s.campaign_id_b = c.campaign_id
INNER JOIN `out` o ON c.campaign_id = o.campaign_id AND s.site_id = o.site_id
WHERE s.site_id NOT IN (100,101))
UNION
(SELECT s.site_id,
s.site_name,
s.campaign_id_a,
s.campaign_id_b,
s.a_display_name,
s.b_display_name,
s.campaign_id_reviews,
s.campaign_id_reviews_phone,
o.out_id,
o.hits,
o.date_last_hit,
c.campaign_id,
c.campaign_name,
c.network,
c.url
FROM sites s
INNER JOIN campaigns c ON s.campaign_id_reviews = c.campaign_id
INNER JOIN `out` o ON c.campaign_id = o.campaign_id AND s.site_id = o.site_id
WHERE s.site_id NOT IN (100,101))
UNION
(SELECT s.site_id,
s.site_name,
s.campaign_id_a,
s.campaign_id_b,
s.a_display_name,
s.b_display_name,
s.campaign_id_reviews,
s.campaign_id_reviews_phone,
o.out_id,
o.hits,
o.date_last_hit,
c.campaign_id,
c.campaign_name,
c.network,
c.url
FROM sites s
INNER JOIN campaigns c ON s.campaign_id_reviews_phone = c.campaign_id
INNER JOIN `out` o ON c.campaign_id = o.campaign_id AND s.site_id = o.site_id
WHERE s.site_id NOT IN (100,101))
ORDER BY site_id ASC
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.