【问题标题】:returning a query with 3 table joins- one being an outer join返回具有 3 个表连接的查询 - 一个是外部连接
【发布时间】:2011-12-21 21:11:02
【问题描述】:

我正在构建一个汽车预订系统,我需要构建的查询是显示系统中所有汽车的查询 - 但每辆车可以同时被 2 人预订。

我只想显示尚未订满或仅由一个人预订的汽车。如果有人预订,我希望能够看到这些人的名字和姓氏,以便其他人知道他们将与谁一起开车。

这是我目前的查询,但它多次返回第一条记录

 SELECT cars.*, people.first_name, people.last_name 
FROM 
    cars 
LEFT JOIN booking on cars.id = booking.car LEFT OUTER JOIN people ON booking.person_1 = people.id
WHERE cars.id NOT IN 
(SELECT car
 FROM booking WHERE slot = 'morning_drive' AND dated = '2011-11-05' AND person_1 != '' AND person_2 != '') AND cars.type = '911' 

这是三个表的结构

CREATE TABLE `cars` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(100) NOT NULL,
  `description` text NOT NULL,
  `large_img_url` varchar(250) NOT NULL,
  `small_img_url` varchar(250) NOT NULL,
  `nr` varchar(100) NOT NULL,
  `license_plate` varchar(100) NOT NULL,
  `exterior_color` varchar(100) NOT NULL,
  `interior_color` varchar(100) NOT NULL,
  `PDK` tinyint(1) NOT NULL,
  `Manual` tinyint(1) NOT NULL,
  `type` enum('911','vintage') NOT NULL,
  `power` varchar(100) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=27 ;



CREATE TABLE `booking` (
  `id` int(11) NOT NULL auto_increment,
  `slot` enum('morning_drive','afternoon_loop','return_drive') NOT NULL,
  `type` enum('911','vintage_911') NOT NULL,
  `car` int(11) NOT NULL,
  `person_1` int(11) default NULL,
  `person_2` int(11) default NULL,
  `dated` date NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=25 ;


CREATE TABLE `people` (
  `id` int(11) NOT NULL auto_increment,
  `first_name` varchar(50) NOT NULL,
  `last_name` varchar(50) NOT NULL,
  `organisation` varchar(100) NOT NULL,
  `event_date` date NOT NULL,
  `wave` varchar(20) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=454 ;

所以我怎样才能让我的查询基本上每辆车只返回一行,只显示没有 (person_2) 和没有 (person_1 或 person_2) 的汽车,如果汽车确实有 person_1-它将检索那个人的名字和姓氏

更新

我发现主选择查询正在返回所有行-我需要将其限制为 slot = 'morning_drive' AND dated = '2011-11-05' 所以它会显示一个人是否为此预订了汽车时间段,但它还需要返回没有用户为该时间段预订的汽车

更新 2

基于实现查询的新要求,我添加了一个左外连接子查询,而不是使用完整的表-

 SELECT cars.*, people.first_name, people.last_name 
FROM 
    cars 
LEFT OUTER JOIN (SELECT car, person_1 FROM booking WHERE  slot = 'morning_drive' AND dated = '2011-11-05' AND booking.person_1 != '' AND booking.person_2 = '') bookings on cars.id = bookings.car LEFT  JOIN people ON bookings.person_1 = people.id
WHERE cars.id NOT IN 
    (SELECT car
 FROM booking WHERE slot = 'morning_drive' AND dated = '2011-11-05' AND person_1 != '' AND person_2 != '')
 AND cars.type = '911'

这更接近我想要返回的内容,但它没有加入人员表 first_names 和 last_names - 它什么也不返回

【问题讨论】:

  • 您是否尝试过 DISTINCT 进行唯一记录检索?
  • 是的,我试过了,但它仍然返回多行
  • @ChrisMccabe,您选择的位置、日期和类型标准似乎与问题中描述的标准无关。这些是额外的标准吗?
  • 您现有的设置将只允许一个人多次预订同一辆车 - 例如,汽车 X1 只能由 John Smith 预订一天,而 Fred Brown 只能在另一天预订.然后,您的查询将返回 car X1 两次,一次为 John Smith,一次为 Fred Brown。
  • 我发现主选择查询正在返回所有行 - 我需要将其限制为 slot = 'morning_drive' AND dated = '2011-11-05' 所以它显示一个人是否有预订了该时间段的汽车,但还需要退回没有用户为该时间段预订的汽车

标签: mysql sql


【解决方案1】:

试试:

SELECT cars.*, people.first_name, people.last_name 
FROM cars 
JOIN booking on cars.id = booking.car
JOIN people on booking.person_1 = people.id
WHERE  booking.slot = 'morning_drive'     AND 
       booking.dated = '2011-11-05'       AND 
       coalesce(booking.person_2,'') = '' AND 
       cars.type = '911'
UNION
SELECT cars.*, '' first_name, '' last_name 
FROM cars
WHERE  cars.type = '911' AND 
       NOT EXISTS
       (SELECT NULL FROM booking 
        WHERE slot = 'morning_drive' AND 
              dated = '2011-11-05'   AND 
              cars.id = bookings.car)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-09
    • 2015-12-11
    • 2018-03-05
    相关资源
    最近更新 更多