SQL выберите со сложными условиями - PullRequest
0 голосов
/ 12 сентября 2018

Я бьюсь головой о каком-то SQL-запросе и в значительной степени его логике.

Предположим, у нас есть эти таблицы:

Таблица отелей

+----+---------+
| id | name    |
+----+---------+
| 1  | Hotel A |
+----+---------+

Стол hotel_rooms

+----+----------+-----------+
| id | hotel_id | room_type |
+----+----------+-----------+
| 1  | 1        | dbl       | <- can be used as A,B,C,D,E,F
| 2  | 1        | dbl       | <- can be used as B,C,D,E,F
| 3  | 1        | sng       | <- can be used as A
| 4  | 1        | trp       | <- can be used as D,E,F
+----+----------+-----------+

Стол hotel_room_usages

+----+---------+-------+
| id | room_id | usage |
+----+---------+-------+
| 1  | 1       | B     |
| 2  | 1       | C     |
| 3  | 1       | A     |
| 4  | 1       | D     |
| 5  | 1       | E     |
| 6  | 1       | F     |
| 7  | 2       | B     |
| 8  | 2       | C     |
| 9  | 2       | D     |
| 10 | 2       | E     |
| 11 | 2       | F     |
| 12 | 3       | A     |
| 13 | 4       | D     |
| 14 | 4       | E     |
| 15 | 4       | F     |
+----+---------+-------+

Если я ищу 2 номера с использованием A или 3 номера с использованием D в качестве отдельных запросов, результатом должен быть отель A с соответствующими идентификаторами номеров.

Проблема в том, что если я ищу 2 номера с использованием A и 3 номера с использованием D, одновременно возвращается и отель A, поскольку он не считает, что некоторые номера могут быть использованы как А и Д.
Номера должны быть уникальными / всего 5 /. Текущий пример не должен возвращать результат, потому что в отеле всего 4 номера.

Ответы [ 2 ]

0 голосов
/ 12 сентября 2018
SELECT h.name AS hotel_name
, q.*
FROM
(
  SELECT r.hotel_id
  , COUNT(DISTINCT CASE WHEN ruA.room_id IS NOT NULL AND ruD.room_id IS NULL THEN ruA.room_id END) AS TotalRoomsOnlyA
  , COUNT(DISTINCT CASE WHEN ruD.room_id IS NOT NULL AND ruA.room_id IS NULL THEN ruD.room_id END) AS TotalRoomsOnlyD
  , COUNT(DISTINCT CASE WHEN ruA.room_id IS NOT NULL AND ruD.room_id IS NOT NULL THEN r.id END) AS TotalRoomsAandD
  , COUNT(DISTINCT r.id) AS TotalRoomsAorD
  FROM hotel_rooms AS r
  LEFT JOIN hotel_room_usages AS ruA ON (ruA.room_id = r.id AND ruA.usage = 'A')
  LEFT JOIN hotel_room_usages AS ruD ON (ruD.room_id = r.id AND ruD.usage = 'D')
  WHERE (ruA.room_id IS NOT NULL OR ruD.room_id IS NOT NULL)
  GROUP BY r.hotel_id
) q
JOIN hotels AS h ON (h.id = q.hotel_id)
CROSS JOIN (SELECT 2 AS a, 3 AS d) AS n
WHERE TotalRoomsAorD >= (a+d)
  AND (
        ((TotalRoomsOnlyA + TotalRoomsAandD) >= a AND TotalRoomsOnlyD >= d) OR
        (TotalRoomsOnlyA >= d AND (TotalRoomsOnlyD + TotalRoomsAandD) >= d) OR
        ((TotalRoomsOnlyA + TotalRoomsAandD/2) >= a AND (TotalRoomsOnlyD + TotalRoomsAandD/2) >= d)
      )
ORDER BY h.name;

Тест по db <> скрипка здесь

0 голосов
/ 12 сентября 2018

это помогает?

- две комнаты с использованием

select id from hotel_room_usages where usage = 'a'

- три комнаты с использованием d

select id from hotel_room_usages where usage = 'd'

- количество номеров с

select count(distinct(room_id)) from hotel_room_usages where usage in ('a','d')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...