副選択を使用して、必要な数量を取得するのがおそらく最善であると考えてください。
accomodation_rooms は、その場所にあるベッドの各数の数 (つまり、1 x 5 ベッドの部屋、2 x 3 ベッド、5 x 2 ベッド) を示すいくつかの宿泊施設の複数の行を格納するテーブルであると仮定します。
SELECT
accomodation.*,
db_cities.title_en AS city,
db_cities.title_url AS city_url,
db_countries.title_url_en AS country_url,
accomodation_rooms.total_persons
FROM
(SELECT id, aid, title_en, title_url_en, address, city_id, zip, district_id, province_id, region_id, country_id, mountain_id, stars, latitude, longitude, picture, valid_from, valid_to
FROM accomodation
ORDER BY info_date_add DESC)
AS accomodation
LEFT JOIN db_cities
ON db_cities.id = accomodation.city_id
JOIN db_countries
ON db_countries.id = accomodation.country_id
JOIN skiresort_locations
ON
(((acos(sin((skiresort_locations.latitude*pi()/180)) *
sin((accomodation.latitude*pi()/180)) +
cos((skiresort_locations.latitude*pi()/180)) *
cos((accomodation.latitude*pi()/180)) *
cos(((skiresort_locations.longitude -
accomodation.longitude)*
pi()/180))))*180/pi())*60*1.1515*1.609344)
< '50'
INNER JOIN (SELECT accomodation_id, SUM(accomodation_rooms.beds * accomodation_rooms.rooms) AS total_persons FROM accomodation_rooms GROUP BY accomodation_id) accomodation_rooms
ON accomodation_rooms.accomodation_id = accomodation.id
AND accomodation_rooms.total_persons >= 1
WHERE db_countries.title_url_en LIKE '%country_title%'
AND accomodation.region_id = '8'
ORDER BY CASE
WHEN accomodation.valid_to>=NOW() AND accomodation.valid_from<=NOW()
THEN 0
WHEN NOW()>accomodation.valid_to AND accomodation.valid_to!='0000-00-00'
THEN 1
ELSE 2
END,
accomodation.title_en
LIMIT 10
OFFSET 0
マイナーな点として、サブ選択として宿泊施設の元の選択が必要かどうかはわかりません (または order by 句がありますが、その中に制限があるようには見えないので、影響はないと思います)。 :-
SELECT
accomodation.id,
accomodation.aid,
accomodation.title_en,
accomodation.title_url_en,
accomodation.address,
accomodation.city_id,
accomodation.zip,
accomodation.district_id,
accomodation.province_id,
accomodation.region_id,
accomodation.country_id,
accomodation.mountain_id,
accomodation.stars,
accomodation.latitude,
accomodation.longitude,
accomodation.picture,
accomodation.valid_from,
accomodation.valid_to,
db_cities.title_en AS city,
db_cities.title_url AS city_url,
db_countries.title_url_en AS country_url,
accomodation_rooms.total_persons
FROM accomodation
LEFT JOIN db_cities
ON db_cities.id = accomodation.city_id
JOIN db_countries
ON db_countries.id = accomodation.country_id
JOIN skiresort_locations
ON
(((acos(sin((skiresort_locations.latitude*pi()/180)) *
sin((accomodation.latitude*pi()/180)) +
cos((skiresort_locations.latitude*pi()/180)) *
cos((accomodation.latitude*pi()/180)) *
cos(((skiresort_locations.longitude -
accomodation.longitude)*
pi()/180))))*180/pi())*60*1.1515*1.609344)
< '50'
INNER JOIN (SELECT accomodation_id, SUM(accomodation_rooms.beds * accomodation_rooms.rooms) AS total_persons FROM accomodation_rooms GROUP BY accomodation_id) accomodation_rooms
ON accomodation_rooms.accomodation_id = accomodation.id
AND accomodation_rooms.total_persons >= 1
WHERE db_countries.title_url_en LIKE '%country_title%'
AND accomodation.region_id = '8'
ORDER BY CASE
WHEN accomodation.valid_to>=NOW() AND accomodation.valid_from<=NOW()
THEN 0
WHEN NOW()>accomodation.valid_to AND accomodation.valid_to!='0000-00-00'
THEN 1
ELSE 2
END,
accomodation.title_en
LIMIT 10 OFFSET 0
編集 - 各エイドの最新の宿泊記録を取得し、それを結合して残りの最新の宿泊記録を取得するように変更しました。
SELECT
accomodation.*,
db_cities.title_en AS city,
db_cities.title_url AS city_url,
db_countries.title_url_en AS country_url,
accomodation_rooms.total_persons
FROM (SELECT aid, MAX(info_date_add) AS max_info_date_add FROM accomodation GROUP BY aid) accomodation_max
INNER JOIN accomodation ON accomodation_max.aid = accomodation.aid AND accomodation_max.max_info_date_add = accomodation.info_date_add
LEFT JOIN db_cities ON db_cities.id = accomodation.city_id
JOIN db_countries ON db_countries.id = accomodation.country_id
JOIN skiresort_locations
ON
(((acos(sin((skiresort_locations.latitude*pi()/180)) *
sin((accomodation.latitude*pi()/180)) +
cos((skiresort_locations.latitude*pi()/180)) *
cos((accomodation.latitude*pi()/180)) *
cos(((skiresort_locations.longitude -
accomodation.longitude)*
pi()/180))))*180/pi())*60*1.1515*1.609344)
< '50'
INNER JOIN (SELECT accomodation_id, SUM(accomodation_rooms.beds * accomodation_rooms.rooms) AS total_persons FROM accomodation_rooms GROUP BY accomodation_id) accomodation_rooms
ON accomodation_rooms.accomodation_id = accomodation.id AND accomodation_rooms.total_persons >= 1
WHERE db_countries.title_url_en LIKE '%country_title%'
AND accomodation.region_id = '8'
ORDER BY CASE
WHEN accomodation.valid_to>=NOW() AND accomodation.valid_from<=NOW()
THEN 0
WHEN NOW()>accomodation.valid_to AND accomodation.valid_to!='0000-00-00'
THEN 1
ELSE 2
END,
accomodation.title_en
LIMIT 10
OFFSET 0
編集 - GROUP BY 句を使用して距離の MIN を追加します。ただし、これが DISTINCT を使用するよりもはるかに高速になるかどうかはわかりません。JOIN で多くの計算が必要になります (つまり、宿泊施設に 100 件のレコードがあり、skiresort_locations に 100 件のレコードがある場合、距離を決定するために 10000 件の合理的な複雑な計算が必要になります。計算を行うと、かなりの時間を節約できます (たとえば、少し非正規化しますが、region_id の宿泊施設に結合する地域テーブルがあり、その地域の最小および最大緯度と経度が含まれている可能性があります)。代わりに、複雑な計算を WHERE 句に入れます。また、db_counties の LIKE 句もあります。
SELECT
accomodation.*,
db_cities.title_en AS city,
db_cities.title_url AS city_url,
db_countries.title_url_en AS country_url,
accomodation_rooms.total_persons,
MIN(((acos(sin((skiresort_locations.latitude*pi()/180)) *
sin((accomodation.latitude*pi()/180)) +
cos((skiresort_locations.latitude*pi()/180)) *
cos((accomodation.latitude*pi()/180)) *
cos(((skiresort_locations.longitude -
accomodation.longitude)*
pi()/180))))*180/pi())*60*1.1515*1.609344)
FROM (SELECT aid, MAX(info_date_add) AS max_info_date_add FROM accomodation GROUP BY aid) accomodation_max
INNER JOIN accomodation ON accomodation_max.aid = accomodation.aid AND accomodation_max.max_info_date_add = accomodation.info_date_add
LEFT JOIN db_cities ON db_cities.id = accomodation.city_id
JOIN db_countries ON db_countries.id = accomodation.country_id
JOIN skiresort_locations
ON
(((acos(sin((skiresort_locations.latitude*pi()/180)) *
sin((accomodation.latitude*pi()/180)) +
cos((skiresort_locations.latitude*pi()/180)) *
cos((accomodation.latitude*pi()/180)) *
cos(((skiresort_locations.longitude -
accomodation.longitude)*
pi()/180))))*180/pi())*60*1.1515*1.609344)
< '50'
INNER JOIN (SELECT accomodation_id, SUM(accomodation_rooms.beds * accomodation_rooms.rooms) AS total_persons FROM accomodation_rooms GROUP BY accomodation_id) accomodation_rooms
ON accomodation_rooms.accomodation_id = accomodation.id AND accomodation_rooms.total_persons >= 1
WHERE db_countries.title_url_en LIKE '%country_title%'
AND accomodation.region_id = '8'
GROUP BY accomodation.id,
db_cities.title_en,
db_cities.title_url,
db_countries.title_url,
accomodation_rooms.total_persons
ORDER BY CASE
WHEN accomodation.valid_to>=NOW() AND accomodation.valid_from<=NOW()
THEN 0
WHEN NOW()>accomodation.valid_to AND accomodation.valid_to!='0000-00-00'
THEN 1
ELSE 2
END,
accomodation.title_en
LIMIT 10
OFFSET 0