views:

271

answers:

5

It appears my SQL isn't limiting results based on price.

In my previous post, http://stackoverflow.com/questions/1039771/sql-help-me-optimize-my-sql, people indicated that I should use a LEFT OUTER JOIN.

SELECT homes.home_id, 
    address, 
    city, 
    state, 
    zip, 
    price, 
    photo_id, 
    photo_url_dir
FROM homes
LEFT OUTER JOIN home_photos ON homes.home_id = home_photos.home_id
AND primary_photo_group_id = home_photo_group_id
AND home_photo_type_id =2
AND display_status = true
AND homes.price BETWEEN 500000 AND 1000000

However, it's still displaying homes whose price is < 500000

I don't understand. Why would the SQL above display homes that have a price less than 500000 when I have a WHERE condition to limit exactly that field.

Thanks for your help.

What I want to do

I want to display both homes with and homes without a home_photo based on criteria like PRICE between X and Y ... or SQFT > Z. But these criteria needs to be applied to both those homes with and those homes without a home_photo

Is this correct?

SELECT homes.home_id, 
    address, 
    city, 
    state, 
    zip, 
    price, 
    photo_id, 
    photo_url_dir
FROM homes
LEFT OUTER JOIN home_photos ON homes.home_id = home_photos.home_id
    AND homes.primary_photo_group_id = home_photos.home_photo_group_id
    AND home_photos.home_photo_type_id =2
WHERE homes.display_status = true
AND homes.price BETWEEN 500000 AND 1000000
+19  A: 

the last line should be using WHERE not AND

WHERE homes.price BETWEEN 500000 AND 1000000

The end result is the following SQL:

SELECT 
    homes.home_id, 
    homes.address, 
    homes.city, 
    homes.state, 
    homes.zip, 
    homes.price, 
    home_photos.photo_id, 
    home_photos. photo_url_dir
FROM 
    homes
    LEFT OUTER JOIN home_photos ON 
        homes.home_id = home_photos.home_id
        AND homes.primary_photo_group_id = home_photos.home_photo_group_id
        AND home_photos.home_photo_type_id =2
WHERE
    homes.price BETWEEN 500000 AND 1000000
    AND homes.display_status = true

EDIT

now your SQFT would go before the WHERE

AND home_photos.home_photo_type_id =2 
AND SQFT <=2000 
WHERE homes.price BETWEEN 500000 AND 1000000
SQLMenace
So are you saying that the AND primary..., AND home_photo_type_ID, AND display_status are apart of the LEFT OUTER JOIN and not apart of the FROM homes
@SQLMenance, also, can I add multiple "AND" where clauses after the "WHERE homes.price BETWEEN 500000 AND 1000000" ?
filter on home_photos (outer table) should be before WHERE and filter on homes (inner table) should be after WHERE
SQLMenace
you can add multiple AND after WHERE but in general should be only for the homes table otherwise you will create an inner join
SQLMenace
@SQLMenance, what I need is for those home that have a home_photo to meet the price criteria AS WELL AS, those homes that do not have a home_photo set to also met the price criteria. Does a LEFT JOIN still work in this case?
I have more than the price criteria to filter on, I also have SQFT, NUM_OF_BEDROOMS that need to be filtered for both the homes with and without a home_photo
the stuff that is in the homes table should go in the WHERE the stuff in the home_photos table in the AND before the WHERE CLAUSE
SQLMenace
@SQLMenace, is what I updated in my original post then correct?
Okay, a WHERE clause and a JOIN clause are NOT the same, even though they behave that way on INNER joins. What the current query is doing is a LEFT JOIN for all of the homes that have a price between 500000 and 1000000, which means that only those homes will be matched to photos. Remember, this is not excluding homes outside of that price range to return, just excluding them from the join condition (they'll have NULLs instead of their photos). A WHERE clause will actually prevent those rows from being returned. (To be continued...)
Eric
Since what the OP wants to do is to exclude the rows, and then do the join, the price of the homes needs to go in the WHERE clause. The ON clause is used _ONLY_ to determine how to match the two tables. The WHERE clause filters results. The reason that an INNER JOIN's ON clause and WHERE clause are interchangable is the definition of an INNER JOIN: It joins the tables and then filters anything that's NULL. Therefore, it accomplishes the task, regardless of whether you tell it to filter (WHERE) or match (JOIN) on certain criteria.
Eric
@Eric, so should I be using an INNER JOIN?
@Jimmy: No, you should be using a LEFT OUTER JOIN, since you want to return the home regardless of whether or not it has photos attached with it. An INNER JOIN will exclude houses that don't have photos. A LEFT OUTER JOIN will bring back all of the houses that meet the WHERE condition, and then find any photos (if they exist) for those houses.
Eric
if you want everything that is in both tables you need an INNER JOIN, if you want everything from the homes table regardless if it exists in the home_photos then you need a OUTER JOIN
SQLMenace
@Eric, would you mind posting the SQL needed to make sure I'm clear as to what it should be
@Jimmy whatever you had posted there before was correct
SQLMenace
@SQLMenance, I want all homes that meet the PRICE criteria plus other criteria like SQFT, regardless if it has a photo or not
@Jimmy: Then you want the LEFT OUTER JOIN. Why not run the query and see the results?
Eric
@SQLMenace, I removed the SQL because MySQL error out. Let me get the code again. The error was something about it was double restricting price < 5000000
@Jimmy: Apply any filters that you want to affect the homes returned (e.g.-SQFT, Price, amenities) in the WHERE clause. The ON clause should _ONLY_ contain conditions for the photos table.
Eric
@Jimmy: Yes. I added the full code to this answer for reference while you were doing that.
Eric
A: 

using where clause as indicated by sqlmenace should work

SQL Baba
Please just up vote the correct answer instead of adding an answer to back up somebody else's answer.
Eric
A: 

Use the join conditions after JOIN keyword and all other filter conditions after the WHERE clause

Rony
A: 

Try this...

SELECT homes.home_id,     
address,     
city,     
state,     
zip,     
price,     
photo_id,     
photo_url_dir
FROM 
homes
LEFT OUTER JOIN 
home_photos ON homes.home_id = home_photos.home_id
AND 
primary_photo_group_id = home_photo_group_id
WHERE 
home_photo_type_id =2
AND 
display_status = true
AND 
homes.price BETWEEN 500000 AND 1000000
Chalkey
If Home_photo_type_id is part of the home_photos table this will not be correct since you are in essence creating an inner join
SQLMenace
That doesn't work because it doesn't return the homes that do not have a primary_photo_group_id set. It only display from the homes table and doesn't include the homes from the home_photos table
A: 

You have all the conditions in the join, you should have some of them in a where clause to limit the query. Something like:

select
   homes.home_id, 
   address, 
   city, 
   state, 
   zip, 
   price, 
   photo_id, 
   photo_url_dir
from
   homes
left join
   home_photos on homes.home_id = home_photos.home_id
where
   primary_photo_group_id = home_photo_group_id and
   home_photo_type_id = 2 and
   display_status = true and
   homes.price BETWEEN 500000 AND 1000000

As I don't know which table each field comes from, I don't know if the above makes sense. Divide the conditions between the join and the where as it fits.

Guffa
no,no,no you just made that an inner join
SQLMenace
@SQLMenace: What are you talking about? Read the code!
Guffa