简体   繁体   English

一对多与三个表联接

[英]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_acampaign_id_bcampaign_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_idsite_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_idcampaign_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM