【问题标题】:How to INNER JOIN around a loop of tables如何围绕表循环进行 INNER JOIN
【发布时间】:2013-12-19 01:32:38
【问题描述】:

我有四个表如下:

CREATE TABLE IF NOT EXISTS `categories` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  PRIMARY KEY (`id`),
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 ;

CREATE TABLE IF NOT EXISTS `categories_friends` (
  `category_id` int(10) unsigned NOT NULL,
  `friend_id` int(10) unsigned NOT NULL,
  UNIQUE KEY `category_id` (`friend_id`,`category_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `friends` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` int(10) unsigned NOT NULL,
  `friend_id` int(10) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `user_id` (`user_id`,`friend_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 ;

CREATE TABLE IF NOT EXISTS `ratings` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` int(10) unsigned NOT NULL,
  `category_id` int(10) unsigned NOT NULL,
  `title` varchar(255) NOT NULL,
  `description` text NOT NULL,
  `rating` tinyint(2) unsigned NOT NULL,
  `public` tinyint(1) NOT NULL DEFAULT '0',
  `created` datetime NOT NULL,
  PRIMARY KEY (`id`),
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 ;

我正在尝试对这些表执行以下查询:

SELECT *
FROM `favred`.`ratings` AS `Rating`
    INNER JOIN `favred`.`friends` AS `JFriend`
        ON (`JFriend`.`friend_id` = `Rating`.`user_id`)
    INNER JOIN `favred`.`categories_friends` AS `JCategoriesFriend`
        ON (`JCategoriesFriend`.`category_id` = `Rating`.`category_id`
            AND `JCategoriesFriend`.`friend_id` = `JFriend`.`id`)
    INNER JOIN `favred`.`categories` AS `JCategory`
        ON (`JCategory`.`id` = `Rating`.`category_id`
            AND `JCategory`.`id` = `JCategoriesFriend`.`category_id`)
WHERE `JFriend`.`user_id` = 1
    AND `Rating`.`user_id` <> 1
    AND `JCategory`.`id` IN (4, 14)
GROUP BY `Rating`.`id`

上面的查询不起作用,因为它没有返回任何结果(尽管表中有应该返回的数据),我想要做的是找到所有不是我创作的评级(ID: 1),但由我的朋友创作,但前提是我已选择查看该朋友的特定类别,结果集由给定的特定类别集过滤。

INNER JOIN 循环通过 Rating --> Friend --> CategoriesFreind --> Category --> 返回到 Rating。

如果我删除 INNER JOIN 的 ON 子句的附加部分,如下所示:

SELECT *
FROM `favred`.`ratings` AS `Rating` 
  INNER JOIN `favred`.`friends` AS `JFriend` 
    ON (`JFriend`.`friend_id` = `Rating`.`user_id`) 
  INNER JOIN `favred`.`categories_friends` AS `JCategoriesFriend` 
    ON (`JCategoriesFriend`.`friend_id` = `JFriend`.`id`) 
  INNER JOIN `favred`.`categories` AS `JCategory` 
    ON (`JCategory`.`id` = `JCategoriesFriend`.`category_id`) 
WHERE `JFriend`.`user_id` = 1 
  AND `Rating`.`user_id` <> 1 
  AND `JCategory`.`id` IN (4, 14) 
GROUP BY `Rating`.`id` 

然后查询将返回结果,但是因为将 CategoriesFriend 加入到 Rating 的 INNER JOIN 没有被 'JCategory'.'id' IN (4, 14) 子句过滤,所以它返回该朋友的所有 Ratings,而不是应有的过滤。

关于如何修改我的查询以获取过滤结果的任何建议?

而且我使用的是 CakePHP,因此尽管不是必需的,但最好使用适合其独特查询格式的查询。

【问题讨论】:

  • +1 提出 SQL 问题并将架构和查询放入其中的人! :-)
  • 您认为必不可少的。
  • 你想要什么样的输出?
  • @AgoengLauw,为简洁起见,我剪掉了SELECT 的一些部分,但基本上,它会提取适合过滤器的评级条目。因此,如果有帮助,您可以将 SELECT * 替换为 SELECT 'Rating'.*

标签: mysql cakephp inner-join


【解决方案1】:

首先,你为什么用JFriend.id,是什么意思,还是和user_id一样?

试试这个,逻辑一样,但从上到下,感觉:

SELECT * FROM categories as JCategory
INNER JOIN categories_friends as JCategoriesFriend ON JCategoriesFriend.category_id = JCategory.id
INNER JOIN friends AS JFriend ON JFriend.friend_id = JCategoriesFriend.friend_id
INNER JOIN ratings AS Rating ON Rating.user_id = JFriend.friend_id
WHERE JCategory.id IN (4,14) AND JFriend.user_id = 1 AND Rating.user_id <> 1 GROUP BY Rating.id

我从为测试制作的所有数据中得到了一个结果。 如果它也不起作用,请尝试制作一些正确的数据,可能数据不正确......

测试数据如下:

categories: id | name (14| 141414)
categories_friends: category_id| friend_id (14| 2)
friends: id | user_id | friend_id (4| 1| 2)
ratings: id | user_id | category_id | title  (2| 2| 14 | 'haha')

【讨论】:

  • 'JFriend'.'id'friends 表的主键。因此,用户 A 通过该表与用户 B 相关联,并且他们获得了一个“友谊”ID(PK),并且该 ID 用于categories_friends 表中以将用户 B 的评级提交过滤到用户 A 关心的某些类别中关于。有意义吗?
  • 不幸的是,该查询与我在原始查询中遇到的问题相同,因为它返回所有评级,而不仅仅是通过过滤条件的评级。
【解决方案2】:

所以我想知道INNER JOINs 在他们的ON 子句中是否过于局限和具体。所以我认为LEFT JOIN 可能会更好......

SELECT * 
FROM `favred`.`ratings` AS `Rating` 
  INNER JOIN `favred`.`friends` AS `JFriend` 
    ON (`JFriend`.`friend_id` = `Rating`.`user_id`) 
  LEFT JOIN `favred`.`categories_friends` AS `JCategoriesFriend` 
    ON (`JCategoriesFriend`.`friend_id` = `JFriend`.`id` 
      AND `JCategoriesFriend`.`category_id` = `Rating`.`category_id`) 
WHERE `JFriend`.`user_id` = 1 
  AND `JRatingsUser`.`id` IS NULL 
  AND `Rating`.`user_id` <> 1 
GROUP BY `Rating`.`id` 

那个查询对我有用。

我取消了直接链接到 categories 表,并通过 categories_friends 表间接链接,这加快了查询速度,一切都很好。

【讨论】:

    猜你喜欢
    • 2010-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-18
    • 2021-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多