我使用的是MySQL 5.7.15SQL子查詢沒有產生正確的結果
我試圖讓where子句(某個位置附近)匹配的所有業務的列表,每個企業我需要獲得最喜歡的照片。如果業務的計劃類型不是1,那麼我需要最喜歡most_liked_picture.business_picture的值爲1的圖片,否則我只需要最喜歡的圖片。爲了做到這一點,我創建了一個外部查詢,該查詢將爲我提供所有業務和一個帶有子查詢的內部查詢,爲我提供滿足order by子句的最喜歡的圖片。
兩個內部查詢不會產生所需的結果。它給出了一些行的結果,但不是全部,我覺得很奇怪。目前我還沒有試圖將內部查詢的結果限制爲每個外部查詢一個,因爲我無法獲得內部查詢子結果來產生正確的結果。
當我打破子查詢出我得到正確的結果,所以我知道查詢是好的,它必須是我把它們合併的方式?
我是在SQL中自學的,所以如果你看到一些不規範或奇怪的東西,請溫和。
這裏是表結構及數據:
businesses
+----+----------------------------+-----------+------------+----------------|
| id | name | lat | lng | point_location |
+----+----------------------------+-----------+------------+----------------|
| 1 | test_business_1 | 28.418908 | -81.586254 | POINT(lng,lat) |
| 2 | Sea_World | 32.764800 | 117.226600 | POINT(lng,lat) |
| 3 | Disneyland | 33.812100 | 117.919000 | POINT(lng,lat) |
| 4 | Disney World | 28.417839 | -81.581235 | POINT(lng,lat) |
| 5 | business near Disney World | 28.408642 | -81.572607 | POINT(lng,lat) |
+----+----------------------------+-----------+------------+----------------|
business_plans
+----+--------------+-------------+---------+------------+------------+
| id | plan_type_id | business_id | user_id | start_date | end_date |
+----+--------------+-------------+---------+------------+------------+
| 1 | 1 | 1 | 1 | 2015-01-01 | 2015-12-31 |
| 2 | 2 | 1 | 2 | 2016-01-01 | 2016-12-31 |
| 3 | 2 | 2 | 2 | 2016-01-01 | 2016-12-31 |
| 4 | 1 | 3 | 1 | 2016-01-01 | 2016-12-31 |
| 5 | 2 | 4 | 1 | 2016-01-01 | 0000-00-00 |
+----+--------------+-------------+---------+------------+------------+
pictures
+----+-------------+---------+---------------------------------------+---------------------------------------+-----------+------------+---------------------------+----------------+-------------------+-------------+----------------+------------------+-----------------------+---------------+---------------------+---------------------+---------------------+---------------------+
| id | business_id | user_id | image_path | title | lat | lng | point_location | lifetime_likes | lifetime_dislikes | month_likes | month_dislikes | business_picture | business_main_picture | business_icon | effective_date | expire_date | updated_at | created_at |
+----+-------------+---------+---------------------------------------+---------------------------------------+-----------+------------+---------------------------+----------------+-------------------+-------------+----------------+------------------+-----------------------+---------------+---------------------+---------------------+---------------------+---------------------+
| 1 | 2 | 1 | sea world image_path_1 | sea world logo | 32.764800 | 117.226600 | POINT(lng,lat) | 5 | 5 | 5 | 5 | 1 | 0 | 1 | 2016-01-01 00:00:00 | 2016-12-31 00:00:00 | 2016-01-01 00:00:00 | 2016-01-01 00:00:00 |
| 2 | 3 | 0 | disney_image_path_2 | disney main picture | 33.812100 | 117.919000 | POINT(lng,lat) | 1 | 0 | 1 | 0 | 1 | 1 | 0 | 2016-01-01 00:00:00 | 2016-12-31 00:00:00 | 2016-01-01 00:00:00 | 2016-01-01 00:00:00 |
| 3 | 3 | 2 | disney user uploaded pic | NULL | 33.812100 | 117.919000 | POINT(lng,lat) | 5 | 5 | 5 | 5 | 0 | 0 | 0 | 2016-01-01 00:00:00 | 2016-12-31 00:00:00 | 2016-01-01 00:00:00 | 2016-01-01 00:00:00 |
| 4 | 3 | 0 | disney expired pic | disney expired pic | 33.812100 | 117.919000 | POINT(lng,lat) | 20 | 0 | 20 | 0 | 1 | 0 | 0 | 2016-01-01 00:00:00 | 2016-01-01 00:00:00 | 2016-01-01 00:00:00 | 2016-01-01 00:00:00 |
| 5 | 3 | 2 | disney_highest_points | disney highest points | 33.812100 | 117.919000 | POINT(lng,lat) | 10 | 2 | 10 | 2 | 1 | 0 | 0 | 2016-01-01 00:00:00 | 2016-12-31 00:00:00 | 2016-01-01 00:00:00 | 2016-01-01 00:00:00 |
| 6 | 4 | 1 | disneyworld_highest_business_pic | disneyworld_highest_business_pic | 28.417839 | -81.581235 | POINT(lng,lat) | 20 | 1 | 20 | 1 | 1 | 0 | 0 | 2016-01-01 00:00:00 | 2016-12-31 00:00:00 | 2016-09-22 22:40:50 | 2016-01-01 00:00:00 |
| 7 | 4 | 1 | disneyworld_highest_user_point_pic | disneyworld_highest_user_point_pic | 28.417839 | -81.581235 | POINT(lng,lat) | 45 | 1 | 45 | 1 | 0 | 0 | 0 | 2016-01-01 00:00:00 | 2016-12-31 00:00:00 | 2016-09-22 22:36:46 | 2016-01-01 00:00:00 |
| 8 | 5 | 2 | near_disneyworld_highest_business_pic | near_disneyworld_highest_business_pic | 28.417839 | -81.581235 | POINT(lng,lat) | 20 | 1 | 20 | 1 | 1 | 0 | 0 | 2016-01-01 00:00:00 | 2016-12-31 00:00:00 | 2016-09-23 00:08:20 | 2016-01-01 00:00:00 |
+----+-------------+---------+---------------------------------------+---------------------------------------+-----------+------------+---------------------------+----------------+-------------------+-------------+----------------+------------------+-----------------------+---------------+---------------------+---------------------+---------------------+---------------------+
users
+----+-----------+--------------------+
| id | username | picture_path |
+----+-----------+--------------------+
| 1 | test | user1_picture_Path |
| 2 | username2 | |
| 3 | username3 | |
| 4 | username5 | |
| 5 | username5 | |
| 6 | username6 | |
| 7 | username7 | NULL |
+----+-----------+--------------------+
user_picture_swipe
+----+------------+-------------+---------+-------+
| id | picture_id | business_id | user_id | liked |
+----+------------+-------------+---------+-------+
| 1 | 1 | 2 | 2 | 0 |
| 2 | 2 | 3 | 2 | 1 |
| 3 | 2 | 3 | 1 | 1 |
| 4 | 3 | 3 | 1 | 1 |
| 5 | 4 | 3 | 1 | 0 |
| 6 | 7 | 4 | 1 | 1 |
| 7 | 6 | 4 | 1 | 0 |
| 9 | 8 | 5 | 2 | 1 |
+----+------------+-------------+---------+-------+
下面是該查詢:
SELECT businesses.id AS business_id, businesses.name AS business_name,
most_liked_picture.business_plan_type_id, most_liked_picture.picture_id,
businesses.lat, businesses.lng, most_liked_picture.image_path,
most_liked_picture.picture_title, most_liked_picture.lifetime_likes,
most_liked_picture.business_picture,
ST_Distance_Sphere(businesses.point_location, POINT(-81.581235, 28.417839)) AS
distance_from_user,
most_liked_picture.uploaded_username,
most_liked_picture.uploaded_user_image_path,
most_liked_picture.user_liked_picture
FROM businesses LEFT JOIN
(SELECT most_liked_picture.id AS picture_id, businesses.id AS business_id,
businesses.name AS business_name,
current_business_plan.plan_type_id AS business_plan_type_id,
businesses.lat, businesses.lng, most_liked_picture.image_path,
title AS picture_title, most_liked_picture.lifetime_likes,
business_picture,
ST_Distance_Sphere(businesses.point_location, POINT(-81.581235,
28.417839)) AS distance_from_user,
CASE business_picture
WHEN 0 THEN user_uploaded_picture.username
ELSE ""
END AS uploaded_username,
CASE business_picture
WHEN 0 THEN user_uploaded_picture.picture_path
ELSE ""
END AS uploaded_user_image_path,
IFNULL(current_user_liked_picture, NULL) AS user_liked_picture
FROM users AS user_uploaded_picture RIGHT JOIN (
(SELECT business_id, plan_type_id
FROM business_plans
WHERE (CURRENT_DATE() BETWEEN start_date AND end_date) OR
((end_date IS NULL) AND (CURRENT_DATE >= start_date))
) AS current_business_plan
RIGHT JOIN (businesses LEFT JOIN (
(SELECT picture_id, liked AS current_user_liked_picture
FROM user_picture_swipes
WHERE (user_id = 1)
) AS user_picture_swipe
RIGHT JOIN pictures AS most_liked_picture
ON user_picture_swipe.picture_id = most_liked_picture.id)
ON businesses.id = most_liked_picture.business_id)
ON current_business_plan.business_id = businesses.id)
ON user_uploaded_picture.id = most_liked_picture.user_id
WHERE ST_Within(businesses.point_location,
envelope(linestring(POINT(-81.581235 - 5/
abs(cos(radians(28.417839)) * 69),28.417839 - (5/69)),
POINT(-81.581235 + 5/abs(cos(radians(28.417839)) * 69),28.417839 +
(5/69)))))
ORDER BY
IF(IFNULL(current_business_plan.plan_type_id, 1) != 1,
IFNULL(most_liked_picture.business_picture, 0), 0) DESC,
lifetime_likes DESC
) AS most_liked_picture ON businesses.id = most_liked_picture.business_id
WHERE ST_Within(businesses.point_location, envelope(linestring(POINT(-81.581235
- 5/abs(cos(radians(28.417839)) * 69),28.417839 - (5/69)),POINT(-81.581235
+ 5/abs(cos(radians(28.417839)) * 69),28.417839 + (5/69)))))
ORDER BY ST_Distance_Sphere(businesses.point_location, POINT(-81.581235,
28.417839));
下面是我得到的結果(縮短至適合頁面):
+-------------+--------------+--------------+-------+----------+---------------+
| business_id | name | plan_type_id | likes | username | liked_picture |
+-------------+--------------+--------------+-------+----------+---------------+
| 4 | Disney World | NULL | 20 | | 0 |
| 4 | Disney World | NULL | 45 | test | 1 |
| 1 | test_business| 2 | | NULL | NULL |
| 5 | business near| NULL | 20 | | NULL |
+-------------+--------------+--------------+-------+----------+---------------+
我應該得到的結果:
+-------------+--------------+--------------+-------+----------+---------------+
| business_id | name | plan_type_id | likes | username | liked_picture |
+-------------+--------------+--------------+-------+----------+---------------+
| 4 | Disney World | 2 | 20 | test | 0 |
| 4 | Disney World | 2 | 45 | test | 1 |
| 1 | test_business| 2 | | NULL | NULL |
| 5 | business near| NULL | 20 | username2| 1 |
+-------------+--------------+--------------+-------+----------+---------------+
對不起,這篇文章太長了。任何幫助表示讚賞。
******************************* ************ ************ *******************
我終於明白了!外部查詢是罪魁禍首,一旦它被刪除,我得到了預期的結果。這是最後一個查詢(在from中沒有使用正確的連接和沒有任何塊)。感謝Used_By_Already爲我指出了正確的方向。
SELECT businesses.id AS business_id, businesses.name AS business_name,
current_business_plan.plan_type_id AS business_plan_type_id, businesses.lat, businesses.lng,
most_liked_picture.id AS picture_id, most_liked_picture.image_path, title AS picture_title,
most_liked_picture.lifetime_likes, business_picture, picture_uploaded_user.username AS uploaded_username,
picture_uploaded_user.picture_path AS uploaded_user_image_path,
user_picture_swipe.current_user_liked_picture AS user_liked_picture,
ST_Distance_Sphere(businesses.point_location, POINT(-81.581235, 28.417839)) AS distance_from_user
FROM
(SELECT business_id, plan_type_id
FROM business_plans
WHERE (CURRENT_DATE() BETWEEN start_date AND end_date) OR ((end_date IS NULL) AND
(CURRENT_DATE >= start_date))) AS current_business_plan
INNER JOIN businesses ON current_business_plan.business_id = businesses.id
LEFT JOIN pictures AS most_liked_picture ON businesses.id = most_liked_picture.business_id
LEFT JOIN users AS picture_uploaded_user ON most_liked_picture.user_id = picture_uploaded_user.id
LEFT JOIN
(SELECT picture_id, liked AS current_user_liked_picture
FROM user_picture_swipes
WHERE (user_id = 1)) AS user_picture_swipe ON most_liked_picture.id = user_picture_swipe.picture_id
WHERE ((expire_date IS NULL) OR (CURRENT_DATE() <= expire_date)) AND
ST_Within(businesses.point_location, envelope(linestring(POINT(-81.581235 - 5/abs(cos(radians(28.417839)) * 69),28.417839 - (5/69)), POINT(-81.581235 + 5/abs(cos(radians(28.417839)) * 69),28.417839 + (5/69)))))
ORDER BY
IF(IFNULL(current_business_plan.plan_type_id, 1) != 1, IFNULL(most_liked_picture.business_picture, 0), 0) DESC,
most_liked_picture.lifetime_likes DESC,
ST_Distance_Sphere(businesses.point_location, POINT(-81.581235, 28.417839))
現在,如果我只想弄清楚如何只返回每個業務1張照片。我嘗試使用聚合MAX(most_liked_picture.lifetime_likes)和GROUP BY的企業.id但是它刪除我的訂單,所以我沒有得到正確的圖片。
你沒有解釋你是如何得到這一結果 – Beginner
我建議你忽略了正確的連接是允許的語法。否認使用它的能力。這會使你更仔細地考慮連接的順序以及用作初始表格的內容(來自.....)。此外,您的示例數據不滿足最終的where子句:請參閱http://sqlfiddle.com/#!9/46d035/1 –
Newbee您是什麼意思解釋我如何得到結果?我在mysqlworkbench中運行查詢,這是你的意思。 – PhishTail