我有两个问题,第一个是:
SELECT * FROM "HOTELS"
LEFT JOIN "ROOM" ON "HOTELS"."HOTEL_ID"="ROOM"."HOTEL_ID"
LEFT JOIN "ROOM_TYPE" ON "ROOM"."ROOM_T"="ROOM_TYPE"."ROOM_T"
WHERE ("ROOM_TYPE"."ROOM_T"='Two beds' AND "HOTELS"."NAME"='Sunset Hotel');
第二个是:
SELECT * FROM "HOTELS"
LEFT JOIN "RESERVATIONS" ON "HOTELS"."HOTEL_ID"="RESERVATIONS"."HOTEL_ID"
WHERE ("HOTELS"."NAME"='Sunset Hotel' AND "RESERVATIONS"."DATE"='7/20/2016');
(我用我的母语翻译了字符串)
好的,我在Oracle的APEX SQL命令页面中运行第一个,它返回4个条目,这是我感兴趣的房间。
我正在运行第二个,它返回我感兴趣的日期的预留房间,1行结果。
现在我想进行减法,这样我只剩下那个在那个日期没有保留的3个房间。
但我尝试使用google搜索后找到的不同格式,并且总是会收到一些无用的错误消息。
答案 0 :(得分:0)
您可以使用left join
并检查匹配项:
SELECT *
FROM "HOTELS" h JOIN
"ROOM" r
ON h."HOTEL_ID" = r."HOTEL_ID" JOIN
"ROOM_TYPE" rt
ON r."ROOM_T" = rt."ROOM_T" LEFT JOIN
"RESERVATIONS" r
ON h."HOTEL_ID" r."HOTEL_ID" AND r."DATE" = '7/20/2016'
WHERE h."NAME= 'Sunset Hotel' AND
rt."ROOM_T"='Two beds' AND
r."HOTEL_ID" IS NULL;
酒店/客房/房型连接不需要LEFT JOIN
。这些ID应该是有效的 - 即使它们不是这样,对房间类型的检查仍然需要匹配。 LEFT JOIN
需要RESERVATIONS
。
答案 1 :(得分:0)
您可以使用LEFT JOIN
包含RESERVATIONS
表,并将日期过滤器作为连接条件的一部分(其他表可以使用INNER JOIN
s):
SELECT *
FROM "HOTELS" h
INNER JOIN "ROOM" r
ON h."HOTEL_ID" = r."HOTEL_ID"
INNER JOIN "ROOM_TYPE" t
ON r."ROOM_T" = t."ROOM_T"
LEFT JOIN "RESERVATIONS" v
ON ( h."HOTEL_ID" = v."HOTEL_ID" AND v."DATE"= DATE '2016-07-20' )
WHERE t."ROOM_T" = 'Two beds'
AND h."NAME" = 'Sunset Hotel'
AND v."HOTEL_ID" IS NULL;
然后,为了测试非预订,您可以检查RESERVATIONS
主键是NULL
(根据最后一行)。
另请注意,如果您要与DATE
数据类型进行比较,那么如果使用字符串值,Oracle将使用TO_DATE()
参数作为格式掩码执行隐式NLS_DATE_FORMAT
- 如果这不匹配则会抛出异常,如果它确实有效,然后参数被更改,它将破坏查询。最好使用日期文字值(例如DATE '2016-07-20'
)。
最后,您可能不需要在所有表和列名称周围使用双引号。默认情况下,Oracle会将列和表名称转换为大写(这是您正在使用的,因此这不是问题)并且双引号标识符的唯一原因是您是否要指定区分大小写的格式(你应该尽量避免)或者你想使用关键字作为名称(你也应该避免)。因此,如果可能,将RESERVATIONS.DATE
列更改为其他名称,因为DATE
是oracle中的关键字(但其余列名称不需要引号)。
答案 2 :(得分:0)
我总是收到一些无用的错误消息
错误消息永远不会无用,实际上它们对于了解您正在做什么或者要求您的RDBMS做错了非常有用。
"预订"" DATE" =&#39 7 /二千零十六分之二十零'
这是错误的,因为您要将 DATE 与字符串文字进行比较。始终使用 TO_DATE 和正确的格式掩码将字符串显式转换为日期。或者,如果您只处理日期部分而不关心时间部分,则使用 ANSI日期文字,它使用固定格式DATE 'YYYY-MM-DD'
回到关于查询的原始要求:
SELECT *
FROM "HOTELS" h
LEFT JOIN "ROOM" r
ON h."HOTEL_ID" = r."HOTEL_ID"
LEFT JOIN "ROOM_TYPE" t
ON r."ROOM_T" = t."ROOM_T"
LEFT JOIN "RESERVATIONS" v
ON ( h."HOTEL_ID" = v."HOTEL_ID"
AND v."DATE" = TO_DATE('2016-07-20', 'YYYY-MM-DD' )
WHERE t."ROOM_T" = 'Two beds'
AND h."NAME" = 'Sunset Hotel'
AND v."HOTEL_ID" IS NULL;
答案 3 :(得分:0)
另一种选择是使用MINUS:
Subquery1
MINUS
Subquery2
https://docs.oracle.com/cd/B19306_01/server.102/b14200/queries004.htm