我有两个表,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”的名称。
答案 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