7

我在实现一个project可以属于多个的模块时遇到问题categories。示例:项目“PHP Programmer”属于类别:编程、PHP。

假设以下查询(选择属于类别 1,3,11 的项目):

SELECT projects.* FROM projects 
    LEFT JOIN pojects_category on projects.id = pojects_category.project_id 
    WHERE pojects_category.category_id IN (1,3,11) and projects.id='94'`

我得到一个相同的项目返回两次,因为表中有2 个匹配=project_categoryproject_id94

projects_category架构:

CREATE TABLE IF NOT EXISTS `pojects_category` (
  `project_id` int(10) NOT NULL,
  `category_id` int(10) NOT NULL,
  KEY `category_id` (`category_id`),
  KEY `project_id` (`project_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;


INSERT INTO `pojects_category` (`project_id`, `category_id`) VALUES
(94, 3),
(94, 1);

我错过了什么吗?

解决方案:使用GROUP BYDISTINCT

4

2 回答 2

10

不,这很好。这只是您想使用DISTINCT关键字删除重复项的极少数情况之一。

在这种情况下,查询的逻辑是正确的这一事实证明了这一点,即使它返回不止一行。很多时候可以看到DISTINCT实际查询逻辑错误时的用法。

边注:

  • 您在WHERE子句中使用的表引用上的任何过滤器,除了IS NULL/IS NOT NULL会使LEFT JOIN同一个表引用上的任何过滤器转向 an INNER JOIN,至于最终结果集行为。(见:https ://stackoverflow.com/a/15483895/1291428 )
  • 您不应该使用GROUP BY来模拟 的效果DISTINCT,原因有两个:

    1/ 这不是目的。的作用之一GROUP BY是消除重复,但其主要目的是根据一组标准对行进行分组,以便对其应用一些分析计算/操作。

    2/GROUP BY还有ORDER BY结果(在mysql中),这不一定是你想要的,在这种情况下会减慢执行速度。请确保正确使用引擎提供的内容,从前向兼容性的角度来看,这总是更好。(预计您包含的内容实际上不是)

问候。

于 2012-07-10T15:08:00.880 回答
1

您还可以将其重写为“IN”以绕过重复项:

SELECT projects.*
FROM projects      
where projects.id in (select project_id
                      from projects_category
                      WHERE pojects_category.category_id IN (1,3,11)
                     ) and
      projects.id='94'

当您使用连接过滤记录时,“in”可防止形成重复。

于 2012-07-10T16:04:16.237 回答