Mysql 一对多连接三个表

Mysql 一对多连接三个表,mysql,join,Mysql,Join,我有一个表格:网站、活动和我正在构建的活动跟踪系统的out。单击链接时,out表会在站点id和活动id匹配的位置更新其命中率 在out表中有一个活动id和一个站点id,这两个id分别对应于站点和活动表。更复杂的是,每个网站可以有4个活动(活动a、活动b、活动id、活动id、活动电话)。我想加入这三个表,对于每个站点,我想在一行上显示以下内容: site.site_name, site.campaign_id_a, campaigns.campaign_name, out.hits, site.

我有一个表格:网站、活动和我正在构建的活动跟踪系统的
out
。单击链接时,out表会在站点id和活动id匹配的位置更新其命中率

在out表中有一个活动id和一个站点id,这两个id分别对应于站点和活动表。更复杂的是,每个网站可以有4个活动(活动a、活动b、活动id、活动id、活动电话)。我想加入这三个表,对于每个站点,我想在一行上显示以下内容:

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
这是我的尝试,它不会返回所有的站点id/活动id组合,它只返回每个站点id的一条记录,而不是所有的站点id/活动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');

问题是您正在覆盖列名称。虽然我还没有测试过它,但它应该可以工作。您可以使用类似的模式获得每个活动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;
编辑1-

根据问题中提供的样本数据,以下查询的结果如下:

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);
结果:

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
回答中的查询结果:

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
请注意,
campaign\u id\u a
campaign\u id\u b
campaign\u id\u reviews
等的活动名称是如何单独获取的

以下是可以为您提供完整答案的查询:

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);
这将为您提供的样本数据集提供一个空结果,因为表
out
中不存在大量
活动id
站点id
组合。由于我们正在进行
内部
加入,您将失去此信息。如果当
站点id
活动id
组合不存在时,您想将
点击次数
报告为
0
,则需要使用
左连接


如果这不是您想要的,请随时恢复。

问题是您正在覆盖列名。虽然我还没有测试过它,但它应该可以工作。您可以使用类似的模式获得每个活动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;
编辑1-

根据问题中提供的样本数据,以下查询的结果如下:

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);
结果:

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
回答中的查询结果:

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
请注意,
campaign\u id\u a
campaign\u id\u b
campaign\u id\u reviews
等的活动名称是如何单独获取的

以下是可以为您提供完整答案的查询:

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);
这将为您提供的样本数据集提供一个空结果,因为表
out
中不存在大量
活动id
站点id
组合。由于我们正在进行
内部
加入,您将失去此信息。如果当
站点id
活动id
组合不存在时,您想将
点击次数
报告为
0
,则需要使用
左连接


如果这不是您想要的,请随时回复。

您似乎参加了两次反对活动,但只返回与compaign\u id\u a匹配的任何内容。在结果中忽略活动标识,而不处理其他两个活动标识

将其拆分以获取每个活动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

您似乎参加了两次反对活动,但只返回与compaign_id_a匹配的任何内容。在结果中忽略活动标识,而不处理其他两个活动标识

将其拆分以获取每个活动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

您可以尝试使用临时表。我认为临时表会使高流量数据库上的事情复杂化,只是为了使它看起来简单,成本高。我不知道如何使用临时表返回生产过程中不需要的所有数据。我只是想更好地理解您的用例。您可以尝试使用临时表。我认为临时表会使高流量数据库上的事情复杂化,只是为了使它看起来简单,成本高。我不知道如何使用临时表返回生产过程中不需要的所有数据。我只是想更好地理解你的用例。虽然我希望它能起作用,但我一直在订单上出错,所以我把它取出来了。然后,我不断地在内部连接“on c.campaign\u id\u a”时出错。我也不完全了解这些工会是如何运作的。我修正了几个拼写错误,现在应该可以运作了。还特别在SELECT语句中列出了列,以避免重复的列名。尽管我很想这样做,但我一直在订单上出错,所以我将其删除。然后,我不断地在内部连接“on c.campaign\u id\u a”时出错。我也不完全了解这些工会是如何运作的。我修正了几个拼写错误,现在应该可以运作了。还特别在SELECT语句中列出了列,以避免重复的列名。我认为这个概念是正确的,但是您创建的查询返回的结果与我问题中的查询相同,没有“内部联接
out
o on s.campaign\u id\u a=o.campaign\u id和s.site\u id=o.site\u id”。我的主要问题是在out表中获取sites表中每个活动id的点击率。我尝试了无数次,试图在out表中添加,但似乎无法找到它。这不会返回相同的结果。在您的情况下,如果删除对
out
的连接,则输出将只返回一个活动名称,即站点表中的活动id。如果您理解这一点,那么您可以轻松地将其扩展到out.hits。这是因为列campaign_name的值是从您进行第一次内部联接时的第一个引用中获取的。我将更新答案以包括out.hits,但了解问题中的查询有什么问题对您来说很重要