2016-09-30 85 views
0

我使用的是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但是它刪除我的訂單,所以我沒有得到正確的圖片。

+0

你沒有解釋你是如何得到這一結果 – Beginner

+0

我建議你忽略了正確的連接是允許的語法。否認使用它的能力。這會使你更仔細地考慮連接的順序以及用作初始表格的內容(來自.....)。此外,您的示例數據不滿足最終的where子句:請參閱http://sqlfiddle.com/#!9/46d035/1 –

+0

Newbee您是什麼意思解釋我如何得到結果?我在mysqlworkbench中運行查詢,這是你的意思。 – PhishTail

回答

1

This simple query

SELECT 
     b.* 
    , bp.business_id 
    , bp.plan_type_id 
    , p.likes 
    , p.b_pic 
    , u.username 
    , u.picture_path 
FROM business_plans AS bp 
INNER JOIN businesses AS b ON bp.business_id = b.id 
left join pictures AS p on b.id = p.id 
left join users AS u on p.user_id = u.id 
WHERE (CURRENT_DATE() BETWEEN bp.start_date AND bp.end_date) 
    OR 
     (bp.end_date IS NULL AND CURRENT_DATE() >= bp.start_date) 

產生這樣的結果:

id name   lat lng point_location business_id plan_type_id likes b_pic username picture_path  
-- --------------- --- --- -------------- ----------- ------------ ----- ----- --------- ------------------ 
1 test_business_1 28 -82 null   1   1   5  1  test  user1_picture_Path 
1 test_business_1 28 -82 null   1   2   5  1  test  user1_picture_Path 
2 Sea_World  33 117 null   2   2   1  1  null  null    
3 Disneyland  34 118 null   3   1   5  0  username2 null    
4 Disney World 28 -82 null   4   2   20 1  null  null    

(5 row(s) returned) 

(25 row(s) affected) 

我建議你從頭開始。

也許這是出發點?至於我,我不知道

SELECT b.*, bp.* 
FROM business_plans AS bp 
INNER JOIN businesses AS b on bp.business_id = b.id 

-- sample data needs start_date or end_date 

WHERE (CURRENT_DATE() BETWEEN start_date AND end_date) 
OR (end_date IS NULL AND CURRENT_DATE >= start_date) 

另外,還要確保您的測試數據將滿足where子句

CREATE TABLE businesses 
    (`id` int, `name` varchar(26), `lat` numeric, `lng` numeric, `point_location` int) 
; 

INSERT INTO businesses 
    (`id`, `name`, `lat`, `lng`, `point_location`) 
VALUES 
    (1, 'test_business_1', 28.418908, -81.586254, NULL), 
    (2, 'Sea_World', 32.764800, 117.226600, NULL), 
    (3, 'Disneyland', 33.812100, 117.919000, NULL), 
    (4, 'Disney World', 28.417839, -81.581235, NULL), 
    (5, 'business near Disney World', 28.408642, -81.572607, NULL) 
; 


CREATE TABLE business_plans 
    (`id` int, `plan_type_id` int, `business_id` int) 
; 

INSERT INTO business_plans 
    (`id`, `plan_type_id`, `business_id`) 
VALUES 
    (1, 1, 1), 
    (2, 2, 1), 
    (3, 2, 2), 
    (4, 1, 3), 
    (5, 2, 4) 
; 


CREATE TABLE pictures 
    (`id` int, `business_id` int, `user_id` int, `lat` int, `lng` int, `point` int, `likes` int, `b_pic` int) 
; 

INSERT INTO pictures 
    (`id`, `business_id`, `user_id`, `lat`, `lng`, `point`, `likes`, `b_pic`) 
VALUES 
    (1, 2, 1, 32.764800, 117.226600, NULL, 5, 1), 
    (2, 3, 0, 33.812100, 117.919000, NULL, 1, 1), 
    (3, 3, 2, 33.812100, 117.919000, NULL, 5, 0), 
    (4, 3, 0, 33.812100, 117.919000, NULL, 20, 1), 
    (5, 3, 2, 33.812100, 117.919000, NULL, 10, 1), 
    (6, 4, 1, 28.417839, -81.581235, NULL, 20, 1), 
    (7, 4, 1, 28.417839, -81.581235, NULL, 45, 0), 
    (8, 5, 2, 28.417839, -81.581235, NULL, 20, 1) 
; 


CREATE TABLE users 
    (`id` int, `username` varchar(9), `picture_path` varchar(18)) 
; 

INSERT INTO users 
    (`id`, `username`, `picture_path`) 
VALUES 
    (1, 'test', 'user1_picture_Path'), 
    (2, 'username2', NULL), 
    (3, 'username3', NULL), 
    (4, 'username5', NULL), 
    (5, 'username5', NULL), 
    (6, 'username6', NULL), 
    (7, 'username7', NULL) 
; 


CREATE TABLE user_picture_swipe 
    (`id` int, `picture_id` int, `business_id` int, `user_id` int, `liked` int) 
; 

INSERT INTO user_picture_swipe 
    (`id`, `picture_id`, `business_id`, `user_id`, `liked`) 
VALUES 
    (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) 
; 
+0

INSERT INTO企業 ('id','name','lat','lng','point_location') VALUES (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,'迪士尼世界附近的商業',28.408642,-81.572607,POINT(lng,lat))這將填充您的point_location列。如果你使用NULL,它將無法工作。 – PhishTail

+0

sqlfiddle剛剛關閉,我沒有MySQL可用,對不起。 –

+0

哪個表應該有列:start_date和end_date?始終在我們的查詢中以表或表別名爲列添加前綴。 –