我有很多桌子,我从哪里做选择,但我只会写一些重要的部分。 我有2张桌子
住宿:
id | title | desc | etc..
accomodation_rooms:
id | accomodation_id | beds | rooms
然后我长期选择哪个有效,直到我想要过滤,有多少床(床*房间)有住宿。如果我尝试从带有乘法的table accomodation_rooms中选择简单,那么效果很好。所以问题应该在某个地方,我加入其他表格。
这是我的选择:
SELECT
accomodation.*,
db_cities.title_en AS city,
db_cities.title_url AS city_url,
db_countries.title_url_en AS country_url,
SUM(accomodation_rooms.beds * accomodation_rooms.rooms) AS 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'
JOIN accomodation_rooms
ON accomodation_rooms.accomodation_id = accomodation.id
WHERE
db_countries.title_url_en LIKE '%country_title%' AND
accomodation.region_id = '8'
GROUP BY
accomodation.aid
HAVING
total_persons >= '1'
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
total_persons应该返回13 但它返回624,但我真的不知道为什么?
答案 0 :(得分:0)
认为通过使用子选择最好获得所需的数量。
我认为accomodation_rooms是一张桌子,可存放多排住宿,说明每个床位数有多少(即1乘5床位,2乘3床位,5乘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个关于调节的记录和100个关于skiresort_locations的记录,那么这将导致10000个合理的复杂计算以确定距离。如果你可以在之前缩小skiresort_locations计算然后这将节省相当多的时间(例如,非规范化一点,但也许你有一个区域表连接到region_id的住宿,它可能包含该区域的最小和最大纬度和经度,你可以使用对于连接,然后将复杂的计算放入WHERE子句中。)你也有一个带有前导通配符的db_counties.title_url_en的LIKE子句,这将很慢,因为它不会使用索引(尽管它应该是在连接上使用country_id索引。
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
答案 1 :(得分:0)
进一步回复新要求。
您需要再次从找到的住宿加入城市表,以获取该住宿的城市详细信息: -
SELECT
accomodation.id,
accomodation.aid,
accomodation.title_$lang,
accomodation.title_url_$lang,
accomodation.address,
accomodation.zip,
accomodation.stars,
accomodation.picture,
accomodation.valid_from,
accomodation.valid_to,
de_cities_accomodation.title_$lang AS city,
de_cities_accomodation.title_url AS city_url,
db_countries.title_url_$lang AS country_url
FROM db_cities
INNER JOIN accomodation
ON
(
db_cities.id = accomodation.city_id
OR
(((acos(sin((db_cities.latitude*pi()/180)) * sin((accomodation.latitude*pi()/180)) + cos((db_cities.latitude*pi()/180)) * cos((accomodation.latitude*pi()/180)) * cos(((db_cities.longitude - accomodation.longitude)*pi()/180))))*180/pi())*60*1.1515*1.609344) < '20' )
INNER JOIN (SELECT aid, MAX(info_date_add) AS max_info_date_add FROM accomodation GROUP BY aid) accomodation_max
ON
accomodation_max.aid = accomodation.aid AND
accomodation_max.max_info_date_add = accomodation.info_date_add
LEFT JOIN db_cities de_cities_accomodation
ON de_cities_accomodation.id = accomodation.city_id
JOIN db_countries
ON db_countries.id = accomodation.country_id
WHERE
db_countries.title_url_en LIKE '%country%' AND
db_cities.title_url LIKE '%city%' AND
db_cities.id = '1258'
GROUP BY accomodation.aid
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