一对多加入三张表

时间:2015-11-17 10:29:04

标签: mysql join

我有一个表格:网站,广告系列和out,用于我正在构建的广告系列跟踪系统。点击链接时,out表会更新其匹配,其中网站ID和广告系列ID匹配。

在out表格中有一个campaign_id和一个site_id,它们分别对应于网站和广告系列表格。更复杂的是,每个网站可以有4个广告系列(campaign_a,campaign_b,campaign_id_reviews,campaign_id_reviews_phone)。我想加入三个表格,对于每个网站,我希望下面的一行:

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

这是我的尝试,它没有带回所有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

我的创建表有3个记录转储:

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');

1 个答案:

答案 0 :(得分:0)

您似乎加入了两次广告系列,但只返回与compaign_id_a相匹配的内容。结果中将忽略Campaign_id_b,而根本不处理其他2个广告系列ID。

将其拆分以获得每个广告系列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