MySQL - 可以简化此查询吗? - 子选择

时间:2013-02-11 18:53:12

标签: php mysql vbulletin

以下是表格和我当前的代码

http://www.sqlfiddle.com/#!2/f1754/6

原样,它有效,但我觉得它可能是资源密集型的......任何想法?

“网”周围的其他人说“子选择”不赞成......

(创建数据库的代码)

CREATE TABLE IF NOT EXISTS `thread_classifieds` (
  `threadid` int(10) NOT NULL,
  `price` decimal(10,2) unsigned DEFAULT NULL,
  `obo` int(5) NOT NULL,
  `offer` int(5) NOT NULL,
  `state` varchar(100) NOT NULL,
  `location` varchar(100) NOT NULL,
  `area` varchar(150) NOT NULL,
  `posttype` varchar(50) NOT NULL,
  `posttype_firearm` varchar(50) NOT NULL,
  `caliber` varchar(100) NOT NULL,
  `manufacturer` varchar(100) NOT NULL,
  `action` varchar(50) NOT NULL,
  `type` varchar(50) NOT NULL,
  UNIQUE KEY `threadid` (`threadid`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

INSERT INTO `thread_classifieds` (`threadid`, `price`, `obo`, `offer`, `state`, `location`, `area`, `posttype`,     `posttype_firearm`, `caliber`, `manufacturer`, `action`, `type`) VALUES
(72, 750.00, 1, 0, 'Kentucky', 'louisville', 'Okolona', 'for-sale', 'handguns', '9mm-luger', 'springfield', 'double-single-action', 'pistol');

CREATE TABLE IF NOT EXISTS `thread_classifieds_action` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `type` int(10) NOT NULL,
  `short` varchar(100) NOT NULL,
  `long` varchar(100) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=21 ;

INSERT INTO `thread_classifieds_action` (`id`, `type`, `short`, `long`) VALUES
(2, 2, 'double-single-action', 'Double / Single Action');

CREATE TABLE IF NOT EXISTS `thread_classifieds_caliber` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `type` int(10) NOT NULL,
  `short` varchar(100) NOT NULL,
  `long` varchar(100) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=211 ;

INSERT INTO `thread_classifieds_caliber` (`id`, `type`, `short`, `long`) VALUES
(46, 2, '9mm-luger', '9mm Luger');

CREATE TABLE IF NOT EXISTS `thread_classifieds_locations` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `forumid` int(10) NOT NULL,
  `short` varchar(100) NOT NULL,
  `long` varchar(100) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=242 ;

INSERT INTO `thread_classifieds_locations` (`id`, `forumid`, `short`, `long`) VALUES
(92, 34, 'louisville', 'Louisville');

CREATE TABLE IF NOT EXISTS `thread_classifieds_manufacturer` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `type` int(10) NOT NULL,
  `short` varchar(100) NOT NULL,
  `long` varchar(100) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=222 ;

INSERT INTO `thread_classifieds_manufacturer` (`id`, `type`, `short`, `long`) VALUES
(67, 2, 'springfield', 'Springfield');

CREATE TABLE IF NOT EXISTS `thread_classifieds_posttype` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `short` varchar(100) NOT NULL,
  `long` varchar(100) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `short` (`short`),
  UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=11 ;

INSERT INTO `thread_classifieds_posttype` (`id`, `short`, `long`) VALUES
(2, 'for-sale', 'For Sale');

CREATE TABLE IF NOT EXISTS `thread_classifieds_posttype_firearm` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `short` varchar(100) NOT NULL,
  `long` varchar(100) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ;

INSERT INTO `thread_classifieds_posttype_firearm` (`id`, `short`, `long`) VALUES
(2, 'handguns', 'Handguns');

CREATE TABLE IF NOT EXISTS `thread_classifieds_type` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `type` int(10) NOT NULL,
  `short` varchar(100) NOT NULL,
  `long` varchar(100) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;

INSERT INTO `thread_classifieds_type` (`id`, `type`, `short`, `long`) VALUES
(2, 2, 'pistol', 'Pistol');

(这是查询)

SELECT 
`price`,    
`obo`,    
`offer`,    
`state`,  
`location` AS `location_org`,  
(SELECT `long` FROM `thread_classifieds_locations` WHERE `short` = `thread_classifieds`.`location` &&     `thread_classifieds`.`threadid` = 72) AS `location_full`,     
`area`,    
(SELECT `long` FROM `thread_classifieds_posttype` WHERE `short` = `thread_classifieds`.`posttype` &&     `thread_classifieds`.`threadid` = 72) AS `posttype`, 
(SELECT `long` FROM `thread_classifieds_posttype_firearm` WHERE `short` = `thread_classifieds`.`posttype_firearm` && `thread_classifieds`.`threadid` = 72) AS `posttype_firearm`, 
(SELECT `id` FROM `thread_classifieds_posttype_firearm` WHERE `short` = `thread_classifieds`.`posttype_firearm` && `thread_classifieds`.`threadid` = 72) AS `typenum`,                                 
(SELECT `long` FROM `thread_classifieds_caliber` WHERE `short` = `thread_classifieds`.`caliber` && `thread_classifieds`.`threadid` = 72 && `thread_classifieds_caliber`.`type` = `typenum`) AS `caliber`,    
(SELECT `long` FROM `thread_classifieds_manufacturer` WHERE `short` = `thread_classifieds`.`manufacturer` && `thread_classifieds`.`threadid` = 72 && `thread_classifieds_manufacturer`.`type` = `typenum`) AS `manufacturer`,   
(SELECT `long` FROM `thread_classifieds_action` WHERE `short` = `thread_classifieds`.`action` && `thread_classifieds`.`threadid` = 72 && `thread_classifieds_action`.`type` = `typenum`) AS `action`,    
(SELECT `long` FROM `thread_classifieds_type` WHERE `short` = `thread_classifieds`.`type` && `thread_classifieds`.`threadid` = 72 && `thread_classifieds_type`.`type` = `typenum`) AS `type`    
FROM `thread_classifieds`    
WHERE `threadid` = 72 LIMIT 1

3 个答案:

答案 0 :(得分:3)

是的,您可以使用联接。我不会在这里重复你的'让我的眼睛流血'的问题,但基本上你已经得到了:

SELECT x, y, (SELECT z FROM othertable WHERE blah blah)

作为联接,它将是

SELECT x, y, sometable.z
FROM sometable
JOIN othertable ON sometable.AAA = othertable.BBB

其中aaa / bbb是将两个表关联在一起的字段。


可能是这样的:

SELECT ..., thread_classifeds_locations.long AS location_full
FROM thread_classifieds
LEFT JOIN thread_classifieds_locations ON thread_classifieds.long = thread_classifieds_locations.long
...
WHERE (thread_classifieds.threadid= 72) AND (thread_classifieds.location = 'short')

答案 1 :(得分:2)

您需要使用连接替换子查询:

select c.`price`,    
  c.`obo`,    
  c.`offer`,    
  c.`state`,  
  c.`location` AS `location_org`,
  l.`long` AS `location_full`,
  c.`area`,
  p.`long` AS `posttype`,
  pf.`long` AS `posttype_firearm`,
  pf.id AS `typenum`,
  cc.`long`  AS `caliber`,
  m.`long`  AS `manufacturer`,
  a.`long`  AS `action`,
  t.`long`  AS `type` 
from thread_classifieds c
left join thread_classifieds_locations l
  on c.location = l.short
left join thread_classifieds_posttype p
  on c.posttype = p.short
left join thread_classifieds_posttype_firearm pf
  on c.posttype_firearm = pf.short
left join thread_classifieds_caliber cc
  on c.caliber = cc.short
  and pf.id = cc.`type`
left join thread_classifieds_manufacturer m
  on c.manufacturer = m.short
  and pf.id = m.`type`
left join thread_classifieds_action a
  on c.action = a.short
  and pf.id = a.`type`
left join thread_classifieds_type t
  on c.type = t.short
  and pf.id = t.`type`
where c.`threadid` = 72 LIMIT 1;

请参阅SQL Fiddle with Demo

答案 2 :(得分:0)

我将您的第一个选择重新作为联接。应该让你开始

SELECT 
`price`,    
`obo`,    
`offer`,    
`state`,  
`location` AS `location_org`,
`posttype`.`long`,
(SELECT `long` FROM `thread_classifieds_locations` WHERE `short` =`thread_classifieds`.`location` && `thread_classifieds`.`threadid` = 72) AS  `location_full`,     
 `area`,    
 (SELECT `long` FROM `thread_classifieds_posttype_firearm` WHERE `short` =  `thread_classifieds`.`posttype_firearm` && `thread_classifieds`.`threadid` = 72) AS `posttype_firearm`, 
 (SELECT `id` FROM `thread_classifieds_posttype_firearm` WHERE `short` = `thread_classifieds`.`posttype_firearm` && `thread_classifieds`.`threadid` = 72) AS `typenum`,                                 
 (SELECT `long` FROM `thread_classifieds_caliber` WHERE `short` = `thread_classifieds`.`caliber` && `thread_classifieds`.`threadid` = 72 && `thread_classifieds_caliber`.`type` = `typenum`) AS `caliber`,    
 (SELECT `long` FROM `thread_classifieds_manufacturer` WHERE `short` = `thread_classifieds`.`manufacturer` && `thread_classifieds`.`threadid` = 72 && `thread_classifieds_manufacturer`.`type` = `typenum`) AS `manufacturer`,   
 (SELECT `long` FROM `thread_classifieds_action` WHERE `short` = `thread_classifieds`.`action` && `thread_classifieds`.`threadid` = 72 && `thread_classifieds_action`.`type` = `typenum`) AS `action`,    
 (SELECT `long` FROM `thread_classifieds_type` WHERE `short` = `thread_classifieds`.`type` && `thread_classifieds`.`threadid` = 72 && `thread_classifieds_type`.`type` = `typenum`) AS `type`    
 FROM `thread_classifieds` AS `thread_classifieds`
INNER JOIN `thread_classifieds_posttype` AS `posttype` ON  `posttype`.`short` = `thread_classifieds`.`posttype` && `thread_classifieds`.`threadid` = 72
WHERE `threadid` = 72 LIMIT 1