是否可以通过单个查询实现此选择?

时间:2010-10-08 22:45:33

标签: mysql

这个人现在已经困扰了我一段时间了.. 我一直在使用MySQL数据库开发自己的CMS;根据与之相关的网站部分,每个上传的图像都被分配到一个类别(我需要这样做,因为每个类别都有自己的处理图像的方式)。

我有各种实体的几个表,一个'images'表和一个关联表:'images_assoc',它们的基本结构如下:

CREATE TABLE `images` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(50) NOT NULL default '',
  `link` varchar(255) NOT NULL default '',
  `idcategory` int(11) NOT NULL default '0',
  PRIMARY KEY  (`id`),
  KEY `idcategory` (`idcategory`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;
INSERT INTO `images` (`id`, `name`, `link`, `idcategory`) VALUES (1, 'some name', 'foo.jpg', 1);
CREATE TABLE `images_assoc` (
  `id` int(11) NOT NULL auto_increment,
  `idimage` int(11) NOT NULL default '0',
  `idelement` int(11) NOT NULL default '0',
  PRIMARY KEY  (`id`),
  KEY `idimage` (`idimage`,`idelement`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;
INSERT INTO `images_assoc` (`id`, `idimage`, `idelement`) VALUES (1, 1, 2);
CREATE TABLE v`some_entity` (
  `id` int(11) NOT NULL auto_increment,
  `title` varchar(250) NOT NULL,
  `description` text NOT NULL,
  -- some other data
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;

在网站的各个页面中,我需要做的是检索页面元素的列表及其相关图像。我还没有能够用一个选择做到这一点。我现在正在做的是为页面元素运行一个select,然后为每个单个元素运行一个查询以检索任何相关的图像,并使用如下查询:

SELECT i.id, i.link, i.name
FROM images_assoc AS ia, images AS i
WHERE ia.idelement = '1'
AND i.idcategory = '1'
AND i.id = ia.idimage
我最初提出的一个解决方案是:

SELECT t. * , i.id, i.link, i.name
FROM (
 (
  (
   contents AS t
  )
  LEFT JOIN images_assoc AS ia ON t.id = ia.idelement
 )
 LEFT JOIN images AS i ON i.id = ia.idimage
)
WHERE i.idcategory = '1'
AND i.id = ia.idimage

但它遗漏了任何没有相关图像的元素,这与左连接的目的完全相反。 后来,我尝试将查询更改为:

SELECT t. * , i.id, i.link, i.name
FROM (
 (
  (
   contents AS t
  )
  LEFT JOIN images_assoc AS ia ON t.id = ia.idelement
 )
 LEFT JOIN images AS i ON ( i.id = ia.idimage
 AND i.idcategoriy = '1' )
)

但是,查询仍然有问题:我最终得到了一个类似交叉连接的结果,因为稍后会应用类别限制。

有没有人有任何建议? 有关数据库结构的任何提示也是受欢迎的。

1 个答案:

答案 0 :(得分:1)

你的idcategory条件永远不会匹配,除非在另一个表中有相应的对应物,这就是为什么没有相应图像的结果“消失”,左连接表现正常。

试试这个:

sql查询:

SELECT some_entity.title, some_entity.description, some_entity.id as entityid, images.id as imageid, images.link, images.name
FROM 
some_entity 
LEFT JOIN images_assoc ON (some_entity.id = images_assoc.idelement)
LEFT JOIN (SELECT * FROM images WHERE idcategory=1) images ON (images.id = images_assoc.idimage)

或者可能更好(obe只是为了说明它为什么不起作用):

SELECT some_entity.title, some_entity.description, some_entity.id AS entityid, images.id AS imageid, images.link, images.name
FROM some_entity
LEFT JOIN images_assoc ON ( some_entity.id = images_assoc.idelement ) 
LEFT JOIN images ON ( images.id = images_assoc.idimage ) 
WHERE images.idcategory =  '1' OR images.idcategory IS NULL 

测试数据:

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
CREATE TABLE IF NOT EXISTS `images` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL DEFAULT '',
  `link` varchar(255) NOT NULL DEFAULT '',
  `idcategory` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `idcategory` (`idcategory`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=124 ;
CREATE TABLE IF NOT EXISTS `some_entity` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(250) NOT NULL,
  `description` text NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=322 ;
CREATE TABLE IF NOT EXISTS `images_assoc` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `idimage` int(11) NOT NULL DEFAULT '0',
  `idelement` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `idimage` (`idimage`,`idelement`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;

INSERT INTO `images` (`id`, `name`, `link`, `idcategory`) VALUES
(123, 'some name', 'foo.jpg', 1);
INSERT INTO `images_assoc` (`id`, `idimage`, `idelement`) VALUES
(1, 123, 321);
INSERT INTO `some_entity` (`id`, `title`, `description`) VALUES
(321, 'test', 'test');