|
|
|
| Суть вроде проста. Есть 3 таблицы: таблица номеров (rooms), таблица возрастных категорий (ages) и таблица связки номеров и возр. категорий (rooms_ages) - то есть, какие возрастные категории могут размещаться в номерах.
Таблица rooms:
+--------------+-----------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-----------------------+------+-----+---------+----------------+
| room_id | int(11) | | PRI | NULL | auto_increment |
| name | varchar(255) | | | | |
+--------------+-----------------------+------+-----+---------+----------------+
|
Таблица ages (здесь age_start, age_end - возраст от и до):
+-----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+----------------+
| age_id | int(11) | | PRI | NULL | auto_increment |
| age_start | tinyint(4) | | | 0 | |
| age_end | tinyint(4) | | | 0 | |
+-----------+-------------+------+-----+---------+----------------+
|
И таблица связки rooms_ages:
+----------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+---------+------+-----+---------+-------+
| room_id | int(11) | | MUL | 0 | |
| age_id | int(11) | | MUL | 0 | |
+----------+---------+------+-----+---------+-------+
|
На входе имеем массив возрастов (количество неизвестно), на пальцах пусть 16 и 25 лет.
Нужно отобрать все комнаты, которые могут принять этих двух поселенцев.
Полдня попыток приводили к каким-то запросам, но не совсем верным. На чем остановился:
SELECT r.* , COUNT(*) AS total
FROM rooms r, ages a1, ages a2, rooms_ages ra1, rooms_ages ra2
WHERE
(
r.room_id = ra1.room_id
AND ra1.age_id = a1.age_id
AND (
a1.age_start <=16
AND a1.age_end >=16
)
)
AND
(
r.room_id = ra2.room_id
AND ra2.age_id = a2.age_id
AND (
a2.age_start <=25
AND a2.age_end >=25
)
)
GROUP BY room_id
|
То есть кол-во таблиц (aN, raN) == количеству поселенцев.
Среди результатов запроса есть правильные данные, но есть и левые, причем total по логике не совсем верный выходит.
Вобщем что-то не так, а что - не пойму.
Да, кстати выбрать сначала все age_id, а потом сделать что-то типа WHERE ... IN () не подходит.
Буду ОЧЕНЬ благодарен за помощь. Если нужны дампы - выложу. | |
|
|
|
|
|
|
|
для: Sync
(08.08.2006 в 02:18)
| | Несовсем понятно, список каких комнат хочется получить.
Нужно чтоб в каждой комнате из результирующего списка можно было поселить
любой из указанных возрастов?
или хотя бы один из указанных возрастов? | |
|
|
|
|
|
|
|
для: Trianon
(08.08.2006 в 09:57)
| | Нужно выбрать комнаты, которые могут принять этих двух поселенцев. Не любой из указанных и не хотябы один, а два сразу, то есть условие 16 И 25. | |
|
|
|
|
|
|
|
для: Sync
(08.08.2006 в 13:30)
| | Так это и есть - любой (каждый) из указанный.
Как-то так:
$list = '16,25'; // = implode(',',array(16,25))
$sql = "SELECT r.name, a.age_start, a.age_end
FROM rooms r, ages a, rooms_ages ra
WHERE r.room_id = ra.room_id AND ra.age_id = a.age_id
AND age_start <= min($list) AND age_end >= max($list)";
|
| |
|
|
|
|
|
|
|
для: Trianon
(08.08.2006 в 14:27)
| | Немного не то... Дело в том, что отношение между таблицами rooms и ages много-ко-многим.
Он вернет результаты, если двое наших поселенцев находятся в ОДНОЙ возрастной категории, если же нет (например 5 лет и 20 лет) - будет empty set. | |
|
|
|
|
|
|
|
для: Sync
(08.08.2006 в 15:36)
| | Показывайте дамп таблиц, пример запроса и ожидаемый результат. Так яснее будет.
(дамп либо в аттаче, либо без обратных косых, т.к. последние тут в репликах искажаются) | |
|
|
|
|
|
|
|
для: Trianon
(08.08.2006 в 16:10)
| |
CREATE TABLE 'ages' (
'age_id' int(11) NOT NULL auto_increment,
'age_start' tinyint(4) NOT NULL default '0',
'age_end' tinyint(4) NOT NULL default '0',
PRIMARY KEY ('age_id')
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
INSERT INTO 'ages' VALUES (1, 2, 15);
INSERT INTO 'ages' VALUES (2, 16, 30);
-- --------------------------------------------------------
CREATE TABLE 'rooms' (
'room_id' int(10) unsigned NOT NULL auto_increment,
'name' varchar(255) NOT NULL default '',
PRIMARY KEY ('room_id')
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
INSERT INTO 'rooms' VALUES (1, 'deluxe');
INSERT INTO 'rooms' VALUES (2, 'bungalo');
-- --------------------------------------------------------
CREATE TABLE 'rooms_ages' (
'room_id' int(11) NOT NULL default '0',
'age_id' int(11) NOT NULL default '0'
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO 'rooms_ages' VALUES (1, 1);
INSERT INTO 'rooms_ages' VALUES (1, 2);
INSERT INTO 'rooms_ages' VALUES (2, 1);
INSERT INTO 'rooms_ages' VALUES (2, 1);
|
При таких данных ваш запрос:
SELECT r.name, a.age_start, a.age_end
FROM rooms r, ages a, rooms_ages ra
WHERE r.room_id = ra.room_id AND ra.age_id = a.age_id
AND age_start <= 4 AND age_end >= 20
|
должен вернуть комнату deluxe (room_id=1), так как есть записи:
то есть она может селить как от 2 до 15, так и от 16 до 30. А в результате ряды не находятся. | |
|
|
|
|
|
|
|
для: Sync
(08.08.2006 в 16:39)
| | Тяжелая задачка. В особенности если INTERSECT нету.
Я добавил таблицу гостей, которых надо селить, с их возрастами guests (guest_id, guest_age)
тогда стал возможен (на 4.1 и выше) такой запрос.
SELECT room_id FROM (SELECT DISTINCT guest_id, room_id
FROM rooms_ages ra JOIN ages a ON ra.age_id=a.age_id
JOIN guests g ON g.age BETWEEN a.age_start AND a.age_end ) AS RES
GROUP BY room_id HAVING COUNT(guest_id) = (SELECT COUNT(*) FROM guests)
|
| |
|
|
|
|
|
|
|
для: Trianon
(08.08.2006 в 19:53)
| | Если вставить в guests возрысты 12 и 13 лет например (первая возрастная категория), то в итоге получим как room_id=1 так и room_id=2, а надо тока room_id=2, так как только она у нас принимает двух человек с первой возр. категории. Может чето поправить надо, щас буду пробовать. | |
|
|
|
|
|
|
|
для: Sync
(08.08.2006 в 21:33)
| | >а надо тока room_id=2, так как только она у нас принимает двух человек с первой возр. категории.
это c каких гвоздей?
собственно, количество человек одной категорией ничем не ограничивается. В таблице даже нет такого поля. | |
|
|
|
|
|
|
|
для: Trianon
(09.08.2006 в 10:07)
| | Еще раз..
Записи :
room_id age_id
1 1
1 2
2 1
2 1
|
означают что комната1 может поселить одного человека от 2 до 15 и еще одного такого же.
а комната2 - одного от 2 до 15 и одного от 16 до 30. никак иначе.
К нам пришло 2 человека по 12 и 13 лет => подходит только комната2.
Да, я понял что вас сбило. Прошу прощения.
Условие - всех пришедших селим в ОДНУ комнату. | |
|
|
|