2016-09-30 8 views
0

Herstellung Ich bin mit MySQL 5.7.15SQL Unterabfrage nicht korrekte Ergebnisse

Ich versuche, eine Liste aller Unternehmen zu erhalten, die die where-Klausel (in der Nähe von einem bestimmten Ort) entspricht, für jedes Geschäft, das mich Müssen das Bild mit den meisten Likes bekommen. Hier wird es kompliziert, wenn das Geschäft einen anderen Plantyp als 1 hat, dann brauche ich das Bild mit den meisten Likes, für die most_liked_picture.business_picture den Wert 1 hat, ansonsten brauche ich nur die Bilder mit den meisten Likes. Bei dem Versuch, dies zu tun, habe ich eine äußere Abfrage erstellt, die mir alle Unternehmen und eine innere Abfrage mit Unterabfragen liefert, um mir das Bild mit den meisten Likes zu geben, das die order by-Klausel erfüllt.

Zwei der inneren Abfragen produzieren nicht die gewünschten Ergebnisse. Es gibt Ergebnisse für einige der Zeilen, aber nicht alle, was ich sehr seltsam finde. Im Moment habe ich nicht versucht, die Ergebnisse der inneren Abfrage auf nur eine pro äußere Abfrage zu beschränken, weil ich die inneren Abfrage-Subs nicht dazu bringen kann, die korrekten Ergebnisse zu erzeugen.

Wenn ich die Unterabfragen auszubrechen ich die richtigen Ergebnisse zu bekommen, damit ich die Abfragen sind gut wissen, hat es die Art und Weise, die ich ihnen bin zu kombinieren?

Ich bin Autodidakt in SQL also wenn Sie etwas sehen, das nicht Standard ist oder ist seltsam, bitte sei sanft.

Hier ist die Tabellenstruktur und Daten:

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 | 
+----+------------+-------------+---------+-------+ 

Hier ist die Abfrage:

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)); 

Hier sind die Ergebnisse erhalte ich (verkürzte Seite passt):

+-------------+--------------+--------------+-------+----------+---------------+ 
| 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 | 
+-------------+--------------+--------------+-------+----------+---------------+ 

Die Ergebnisse sollte ich bekommen:

+-------------+--------------+--------------+-------+----------+---------------+ 
| 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 | 
+-------------+--------------+--------------+-------+----------+---------------+ 

Entschuldigung, dieser Beitrag ist so lang. Jede Hilfe wird geschätzt.

******************************* Update für die Suche nach ************ *******************

Ich endlich herausgefunden! Die äußere Frage war der Täter, sobald es entfernt wurde, bekam ich die gewünschten Ergebnisse. Hier ist die letzte Abfrage (ohne rechte Joins und keine Blöcke im from). Danke an Used_By_Already, um mich in die richtige Richtung zu weisen.

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)) 

Jetzt, wenn ich nur herausfinden könnte, wie man nur 1 Bild für jedes Geschäft zurückgibt. Ich habe versucht, ein Aggregat MAX (most_liked_picture.lifetime_likes) und GROUP BY businesss.id verwendet, aber es entfernt meine Bestellung von, damit ich nicht das richtige Bild bekommen.

+0

Sie nicht erklären, wie man dieses Ergebnis bekommen haben – Beginner

+0

Ich schlage vor, Sie ignorieren, dass Recht kommen ist zulässige Syntax Verweigern Sie sich die Fähigkeit, es zu benutzen. Dies wird dazu führen, dass Sie - sorgfältiger - die Reihenfolge der Joins und die Verwendung als Anfangstabelle (von .....) betrachten. Auch Ihre Beispieldaten erfüllen nicht die endgültige where-Klausel: siehe http://sqlfiddle.com/#!9/46d035/1 –

+0

Newbee was meinst du, erklären, wie ich das Ergebnis bekommen habe? Ich habe die Abfrage in mysqlworkbench ausgeführt, meinst du das? – PhishTail

Antwort

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) 

erzeugt ein Ergebnis wie folgt aus:

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) 

ich Sie von Grund auf neu starten vorschlagen.

Vielleicht dies ist der Ausgangspunkt?Aber wirklich bin ich nicht sicher,

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) 

Vergewissern Sie sich auch Ihre Testdaten werden die where-Klauseln erfüllen

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 Unternehmen ('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.417.839, -81.581235, POINT (lng, lat)), (5, 'Geschäft in der Nähe von Disney World', 28.408642, -81.572607, POINT (lng, lat)) Dies wird Ihre point_location-Spalte füllen. Wenn Sie NULL verwenden, wird es nicht funktionieren. – PhishTail

+0

sqlfiddle ist gerade runter gegangen und ich habe keine MySQL-Datenbank, sorry. –

+0

Welche Tabelle soll Spalten haben: start_date und end_date? IMMER eine Spalte durch die Tabelle oder den Tabellenalias in unseren Abfragen voranstellen. –