Me han dado las siguientes tablas:

Hotel (hotelNo, hotelName,hotelAddress)   
Room (roomNo,hotelNo, type, price)
Guest (guestNo, guestName, guestAddress)
Booking (hotelNo,guestNo,dateFrom, dateTo, roomNo)

La pregunta pregunta: "¿Cuál es el porcentaje de hoteles que aún están en construcción? Indique el número total de hoteles, el número de hoteles terminados, el número de hoteles en construcción y el porcentaje de hoteles en construcción".

Para el número total de hoteles, sé que puedo hacer esto:

SELECT COUNT(Hotel.hotelNo)
FROM HOTEL;

Hay 2 hoteles en construcción que sé que puedo verificar si usan:

SELECT COUNT(Hotel.hotelNo)
FROM HOTEL
INNER JOIN ROOM
ON ROOM.hotelNo = Hotel.hotelNo
HAVING COUNT(roomNo) = 0;

Y luego hoteles que se completan:

SELECT COUNT(Hotel.hotelNo)
FROM HOTEL
INNER JOIN ROOM
ON ROOM.hotelNo = Hotel.hotelNo
HAVING COUNT(roomNo) > 0;

Sin embargo, no sé cómo haría para poner todo esto en una consulta. Intenté algo como esto:

SELECT COUNT(Hotel.hotelNo),
(SELECT COUNT(Hotel.hotelNo)
FROM HOTEL
LEFT JOIN ROOM
ON ROOM.hotelNo = Hotel.hotelNo
GROUP BY Room.roomNo
HAVING COUNT(roomNo) = 0) as count
FROM HOTEL;

Sin embargo, eso requiere que tenga un grupo por declaración para Hotel.hotelNo pero cuando se agrega solo me da una tabla de 10 1 para COUNT(Hotel.hotelNo) porque hay 10 hoteles y luego 10 2 porque hay 2 hoteles en construcción para todos esas entradas.

Quiero que se vea así:

TOTAL COMPLETED CONSTRUCTION PERCENTAGE
---------------------------------------
   10         8            2         20

¿Cómo haría esto?

1
bluewave41 26 ene. 2015 a las 03:31

2 respuestas

La mejor respuesta

Puedes probar algo como esto:

SELECT tmp.*
     , (tmp.total-tmp.complete) AS construction
     , ((1-tmp.complete/tmp.total)*100) AS percentage
FROM ( SELECT COUNT(DISTINCT h.hotelNo) AS total
            , COUNT(DISTINCT r.hotelNo) AS complete
       FROM HOTEL h 
       LEFT JOIN ROOM r ON r.hotelNo = h.hotelNo ) tmp

SQLFiddle

1
potashin 26 ene. 2015 a las 01:37

Me sorprendería si su consulta para conseguir hoteles en construcción,

SELECT COUNT(Hotel.hotelNo)
FROM HOTEL
INNER JOIN ROOM
ON ROOM.hotelNo = Hotel.hotelNo
HAVING COUNT(roomNo) = 0;

Realmente funcionó. La razón por la que digo esto es que parece una consulta que debería ser una combinación izquierda, buscando valores de hotelNo para los cuales no hay filas correspondientes en ROOM.

Así es como puede juntar las dos consultas:

SELECT COUNT(*) AS total
     , SUM(DECODE(room_cnt, 0, 0, 1)) AS completed
     , SUM(DECODE(room_cnt, 0, 1, 0)) AS construction
     , SUM(DECODE(room_cnt, 0, 1, 0))/COUNT(*) AS percentage
  FROM (
    SELECT h.hotelNo, COUNT(r.roomNo) AS room_cnt
      FROM hotel h LEFT JOIN room r
     WHERE h.hotelNo = r.hotelNo
     GROUP BY h.hotelNo
);

Puede usar CASE en lugar de DECODE() si le gusta ANSI SQL.

0
David Faber 26 ene. 2015 a las 04:16