我很困惑加入

时间:2009-12-28 17:46:11

标签: sql mysql join

我有两个表,omc_categories和omc_products。

我想提取类别名称,其中omc_proudcts.category_id等于omc_categories.id。

我创建了以下sql,但我不确定哪个是正确的。

SELECT C.Name AS CatName
   FROM omc_categories AS C
   LEFT JOIN omc_products AS P
     ON C.id = P.category_id
   WHERE P.category_id = $category_id
     AND p.status = "active"

SELECT C.Name AS CatName
   FROM omc_products AS P
   LEFT JOIN omc_categories AS C
     ON C.id = P.category_id
   WHERE P.category_id = $category_id
     AND p.status = "active"

任何人都可以告诉我哪一个正确(如果有的话)以及为什么请。我对加入感到困惑。

CREATE TABLE IF NOT EXISTS `omc_categories` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `shortdesc` varchar(255) NOT NULL,
  `longdesc` text NOT NULL,
  `status` enum('active','inactive') NOT NULL,
  `parentid` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=43 ;

CREATE TABLE IF NOT EXISTS `omc_products` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `shortdesc` varchar(255) NOT NULL,
  `longdesc` text NOT NULL,
  `thumbnail` varchar(255) NOT NULL,
  `image` varchar(255) NOT NULL,
  `class` varchar(255) DEFAULT NULL,
  `grouping` varchar(16) DEFAULT NULL,
  `status` enum('active','inactive') NOT NULL,
  `category_id` int(11) NOT NULL,
  `featured` enum('true','false') NOT NULL,
  `price` float(4,2) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=74 ;

- UPDATE -

omc_categories

的示例数据
INSERT INTO `omc_categories` (`id`, `name`, `shortdesc`, `longdesc`, `status`, `parentid`) VALUES
(21, 'Front top', 'front top', '', 'active', 4),
(20, 'Galleri 2', 'Galleri 2', '', 'active', 4),
...
(41, 'Trær', '', '', 'active', 27),
(42, 'newfolder', '', '', 'active', 27);

omc_products的样本数据

    INSERT INTO `omc_products` (`id`, `name`, `shortdesc`, `longdesc`, `thumbnail`, `image`, `class`, `grouping`, `status`, `category_id`, `featured`, `price`) VALUES
(1, 'Doggie', 'Cappelen forlag: New Flight', 'Doggie from New flight.', 'images/newflight_doggie_small.jpg', 'images/newflight_doggie_big.jpg', 'new-flight', 'imagebox-new', 'active', 5, 'false', 0.00),
(2, 'Jinnie', 'New flight Jinnie', '', 'images/newflight_jinnie_small.jpg', 'images/newflight_jinnie_big1.jpg', 'new-flight', 'imagebox-new', 'active', 5, 'false', 0.00),
...
...
(73, 'new image', '', '', 'images/daffodil_big.jpg.jpg', 'images/daffodil_big.jpg', '', '', 'active', 42, 'false', 0.00);

例如,最后一行ID 73包含42个category_id。

我想从omc_categories中提取类别“newfolder”的名称。

5 个答案:

答案 0 :(得分:3)

正如Arthur Thomas指出的那样,你的语句的问题是左连接将包括左表中的所有行,当ON子句失败时,使用NULL作为来自右表的列的值。普通(内部)连接仅包含ON子句成功的行。

SELECT DISTINCT C.Name AS CatName
   FROM omc_categories AS C
   JOIN omc_products AS P
     ON C.id = P.category_id
        AND P.category_id = $category_id
   WHERE p.status = "active"

请注意,您可以在ON子句中包含常量表达式,这会减少连接的大小(稍后添加行时没有任何意义)。

小心你如何建立声明。您不希望它容易受到SQL injection的攻击。<​​/ p>

答案 1 :(得分:2)

如果您想要将omc_proudcts.category_id等于omc_categories.id的类别名称拉出来,以下内容应该为您做到(除非我遗漏了某些内容......):

SELECT C.Name AS CatName
   FROM omc_categories AS C
   INNER JOIN omc_products AS P
     ON C.id = P.category_id
   WHERE p.status = "active"

INNER JOIN表示加入这些表,这两个值彼此相等(与“WHERE C.id = P.category_id”相同)

答案 2 :(得分:0)

最有可能的是,你想要这个:

SELECT  name
FROM    omc_categories
WHERE   id IN
        (
        SELECT  category_id
        FROM    products
        WHERE   status = 'active'
        )
        AND id = $id

如果此类别中有活动产品,则会返回类别名称,否则无效。

答案 3 :(得分:0)

首先,它们都是错误的$ category_id未定义。

其次,如果删除该行

WHERE P.category_id = $category_id

(这是过分的)他们都是正确的,除非你有category_id NOT NULL,否则结果会有所不同。因为它不能为空,它们就是一样的。以及内连接或外连接。

顺便说一下,如果你告诉数据库,category_id实际上是一个外键,那就太好了。)

答案 4 :(得分:0)

您想使用内部联接...重建查询的最简单方法是:

SELECT C.Name AS CatName
   FROM omc_categories AS C
   INNER JOIN omc_products AS P
     ON C.id = P.category_id
   WHERE P.category_id = $category_id
     AND p.status = "active"

内连接将给出两个表之间的交集,在两个表共有的ID上(分类中的id,产品中的category_id)。

解决问题的更好方法(显示所有具有有效产品的类别)是:

SELECT C.Name AS CatName
   FROM omc_categories AS C
   where exists (Select * from omc_products AS P where p.categoryID = c.id)

这与in语句类似。

如果您想知道每个类别有多少产品,请尝试以下方法:

SELECT C.Name AS CatName, count(p.*), sum(case when p.status = "active" then 1 else 0 end) as numActiveProducts
   FROM omc_categories AS C
   left outer JOIN omc_products AS P
     ON C.id = P.category_id 
group by c.name