SQL Query Help - Is subquery needed?

Discussion in 'PHP' started by fri3ndly, Feb 8, 2011.

  1. #1
    Hello

    I have a table called 'resorts' with details of hotels. There is a table called features_list which holds details of features at resorts. Finally there is a table which links the two together called featuers_resorts (has resort id and feature id).

    Basically the idea is that on the frontend a user can click what features they would like from a list and then the site queries this database to fetch results that include ALL of the selected.

    If you look at this query you will see the problem:
    
    SELECT * FROM resorts 
    INNER JOIN resorts_features 
    ON resorts.id = resorts_features.resort_id 
    WHERE (resorts.star_rating = '4') 
    [B]AND resorts_features.feature_id = '11'
    AND resorts_features.feature_id = '21' 
    AND resorts_features.feature_id = '14' 
    AND resorts_features.feature_id = '23' 
    AND resorts_features.feature_id = '7'[/B]
    
    Code (markup):
    The part that I have made bold is the problem and obviously won't return results as expected. How can I write this? I can only think of a subquery but a little lost?

    Thanks for your help
     
    fri3ndly, Feb 8, 2011 IP
  2. seoelk.com

    seoelk.com Peon

    Messages:
    19
    Likes Received:
    1
    Best Answers:
    0
    Trophy Points:
    0
    #2
    I'm not really sure this is a good way and if it will work, but the first thing came to my mind is something like:
    
    SELECT * FROM resorts 
    WHERE (resorts.star_rating = '4') AND 
               (SELECT count(id)
                FROM resorts_features as a  
                WHERE  resorts.id = resorts_features.resort_id AND
                           resorts_features.feature_id in ('11', '21', '14')) = 3 --here goes --feature count
    
    
    PHP:
    and i didn't check syntax
     
    seoelk.com, Feb 8, 2011 IP
  3. plog

    plog Peon

    Messages:
    298
    Likes Received:
    11
    Best Answers:
    1
    Trophy Points:
    0
    #3
    Your WHERE clause is incorrect. You are essentially asking for hotels who's feature_id field contains 5 different values--which is impossible, it can only hold 1 value. You want to replace the ANDs between those with ORs like this:

    WHERE (resorts.star_rating = '4') AND
    (resorts_features.feature_id = '11' OR resorts_features.feature_id = '21'  OR resorts_features.feature_id = '14' OR resorts_features.feature_id = '23' OR resorts_features.feature_id = '7') 
    
    PHP:
    That way instead of the feature_id having to be all 5 values, it has to only be one of those 5 to show.
     
    plog, Feb 9, 2011 IP
  4. seoelk.com

    seoelk.com Peon

    Messages:
    19
    Likes Received:
    1
    Best Answers:
    0
    Trophy Points:
    0
    #4
    oh yeah people definetly will be looking for hotels that have swimming pool OR tennis court OR air conditioning :)
     
    seoelk.com, Feb 9, 2011 IP
  5. plog

    plog Peon

    Messages:
    298
    Likes Received:
    11
    Best Answers:
    1
    Trophy Points:
    0
    #5
    seoelk.com is right--my previous post is wrong--don't use it. I thought you were looking up specific hotels, not specific features.
     
    plog, Feb 9, 2011 IP
  6. fri3ndly

    fri3ndly Active Member

    Messages:
    111
    Likes Received:
    5
    Best Answers:
    0
    Trophy Points:
    60
    #6
    Hi everyone & thanks for the replies.

    Indeed plog - so you see my dilemma :(

    Thanks for that example soelk, will have a go... any chance you can explain the 'here goes feature count' bit?
     
    fri3ndly, Feb 9, 2011 IP
  7. mastermunj

    mastermunj Well-Known Member

    Messages:
    687
    Likes Received:
    13
    Best Answers:
    0
    Trophy Points:
    110
    #7
    Following should help..

    
    SELECT col1, col2, col3, [..col-N] FROM resorts A
    JOIN 
    (SELECT DISTINCT resort_id FROM resorts_features WHERE feature_id IN(11, 21, 14, 23, 7)) B
    ON A.resort_id = B.resort_id
    WHERE A.star_rating = 4
    
    Code (markup):
    I've assumed that feature_id & star_rating columns are numeric and hence have removed quotes from around values.
    Also, added DISTINCT in sub-query to avoid multiple entries of same resort in final result.
     
    mastermunj, Feb 9, 2011 IP
    fri3ndly likes this.
  8. fri3ndly

    fri3ndly Active Member

    Messages:
    111
    Likes Received:
    5
    Best Answers:
    0
    Trophy Points:
    60
    #8
    Thanks mastermunj

    I ran it through SQL on mysql and got the following:

    [B]Error
    
    SQL query: Documentation[/B]
    
    SELECT *
    FROM resorts
    JOIN (
    
    SELECT DISTINCT resort_id
    FROM resorts_features
    WHERE feature_id
    IN ( 11, 21, 14, 23, 7 )
    ) ON resorts.resort_id = resorts_features.resort_id
    WHERE resorts.star_rating =4
    LIMIT 0 , 30
    
    [B][COLOR="red"]MySQL said: Documentation
    #1248 - Every derived table must have its own alias[/COLOR][/B] 
    Code (markup):
     
    fri3ndly, Feb 9, 2011 IP
  9. mastermunj

    mastermunj Well-Known Member

    Messages:
    687
    Likes Received:
    13
    Best Answers:
    0
    Trophy Points:
    110
    #9
    It seems you edited the query.
    You removed A & B aliases I had used. Either use them, or use other ones you like.
    Basically, the inner select query generates a derived table, which must have an alias, and hence the error.
    Try running the query I gave as it is and verify if results are as desired or not.
     
    mastermunj, Feb 9, 2011 IP
  10. mco65

    mco65 Member

    Messages:
    144
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    38
    #10
    SELECT * FROM resorts
    INNER JOIN resorts_features
    ON resorts.id = resorts_features.resort_id
    WHERE ((resorts.star_rating) = '4')
    AND ((resorts_features.feature_id) = '11')
    AND ((resorts_features.feature_id) = '21')
    AND ((resorts_features.feature_id) = '14')
    AND ((resorts_features.feature_id) = '23'))
    AND ((resorts_features.feature_id) = '7');
     
    mco65, Feb 9, 2011 IP
  11. fri3ndly

    fri3ndly Active Member

    Messages:
    111
    Likes Received:
    5
    Best Answers:
    0
    Trophy Points:
    60
    #11
    I thought I would have to edit it slightly.

    Here it is with nothing amended:

    [B]Error
    
    SQL query: Documentation[/B]
    
    SELECT col1, col2, col3, [..col - N]
    FROM resorts A
    JOIN (
    
    SELECT DISTINCT resort_id
    FROM resorts_features
    WHERE feature_id
    IN ( 11, 21, 14, 23, 7 )
    )B ON A.resort_id = B.resort_id
    WHERE A.star_rating =4
    LIMIT 0 , 30
    
    [B][COLOR="red"]MySQL said: Documentation
    #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '[ . . col - N ] FROM resorts A  JOIN  ( SELECT DISTINCT resort_id FROM resorts_f' at line 1 [/COLOR][/B]
    
    Code (markup):
    And here is it with the col1,col2,col3 changed to just name (one of the column names):

    
    [B]Error
    
    SQL query: Documentation[/B]
    
    SELECT name
    FROM resorts A
    JOIN (
    
    SELECT DISTINCT resort_id
    FROM resorts_features
    WHERE feature_id
    IN ( 11, 21, 14, 23, 7 )
    )B ON A.resort_id = B.resort_id
    WHERE A.star_rating =4
    LIMIT 0 , 30
    
    [B][COLOR="red"]MySQL said: Documentation
    #1054 - Unknown column 'A.resort_id' in 'on clause' [/COLOR][/B]
    
    Code (markup):
     
    fri3ndly, Feb 9, 2011 IP
  12. fri3ndly

    fri3ndly Active Member

    Messages:
    111
    Likes Received:
    5
    Best Answers:
    0
    Trophy Points:
    60
    #12
    MySQL said: Documentation
    #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ') AND ( ( resorts_features . feature_id ) = '7' )
    LIMIT 0, 30' at line 1
     
    fri3ndly, Feb 9, 2011 IP
  13. fri3ndly

    fri3ndly Active Member

    Messages:
    111
    Likes Received:
    5
    Best Answers:
    0
    Trophy Points:
    60
    #13
    I sorted the syntax but it returned 0 results - this is the same as my query, you have just put brackets around bits which hasn't made a difference ;-)
     
    fri3ndly, Feb 9, 2011 IP
  14. fri3ndly

    fri3ndly Active Member

    Messages:
    111
    Likes Received:
    5
    Best Answers:
    0
    Trophy Points:
    60
    #14
    SOLVED!!

    Thanks to mastermunj

    It was just the column was resorts.id not resorts.resort_id.

    Looks like its working as intended....you legend!

    Thanks again
     
    fri3ndly, Feb 9, 2011 IP
  15. mastermunj

    mastermunj Well-Known Member

    Messages:
    687
    Likes Received:
    13
    Best Answers:
    0
    Trophy Points:
    110
    #15
    I'm glad I could help.

    I wrote col1, col2, col3 because we must avoid using * as much as possible.
     
    mastermunj, Feb 9, 2011 IP