1

I am fairly new with advanced MySQL commands, I have database tables with multiple relationships. I have an advanced search feature that must match Keywords to a few fields (most being in the Assets table but a couple in the User table). When I execute the following Query for desk it returns the same row multiple times, while it should do it once.

 SELECT 
   a.id, a.asset_id, a.name, a.serial_number, a.category_id, a.status_id, a.user_id, a.location_id 
 FROM 
   assets a, users u 
 WHERE 
  (a.asset_ID LIKE '%desk%' OR a.name LIKE '%desk%' OR (u.first_name LIKE '%desk%' OR u.last_name LIKE '%desk%')) AND 
  a.serial_number LIKE '%%' AND 
  a.category_id='2' 
 LIMIT 25 OFFSET 5450 
2
  • Can you paste a sample of the output? Commented Jul 14, 2011 at 14:33
  • Is the query matching the search keywords multiple times in a single row? This could get you on the right track Commented Jul 14, 2011 at 14:34

4 Answers 4

10

You have a cartesian product in your query. You should JOIN assets and users, e.g. with

WHERE a.user_id = u.id

or like this

FROM assets a JOIN users u ON a.user_id = u.id

UPDATE: Your comment shows that you actually want to "left outer join" the users table. This means, that all assets are in the result set regardless if there exists a matching user:

FROM assets a LEFT OUTER JOIN users u ON a.user_id = u.id

Read more about joining tables here: http://dev.mysql.com/doc/refman/5.5/en/join.html

Sign up to request clarification or add additional context in comments.

5 Comments

Please prefer the latter though. Keeping join criteria and selection criteria separate makes for better readability.
@Yuck: Absolutely. But one step at a time for newbies :-)
Thank you, this is the exact thing it was missing.
@Travis: Generally, if your records seem to duplicate (also in much more complex queries), you can always search for cartesian products first. 95% you'll find the problem there
There is a new problem I am running into with this, if the Asset is not assigned to a user it is not showing up, even if searched for. I am assuming it is because it has no match for a.user_id = u.id. Is there a way to maybe add OR a.user_id = NULL (I already tried this, but it didn't work)?
1

You could use a SELECT DISTINCT clause, though the actual problem looks like the one made by Lukas. It's good practice to use explicit joins like so:

 FROM assets a
 JOIN users u ON a.user_id=u.id

1 Comment

Hmm, true. DISTINCT would be correct in this case, without projections from users. Your DBA would kill you ;-)
1

You need to actually join the two tables (Assets and Users) together. As you have it, every row in each table is matched with every row in the other. This is known as a Cartesian Product and is usually a bad thing.

I would also suggest that you start using proper JOIN syntax:

SELECT
    a.id,
    a.asset_id,
    a.name,
    a.serial_number,
    a.category_id,
    a.status_id,
    a.user_id,
    a.location_id
FROM
    Assets A
INNER JOIN Users U ON A.user_id = U.user_id
WHERE
    (
        a.asset_ID LIKE '%desk%' OR
        a.name LIKE '%desk%' OR
        (
            u.first_name LIKE '%desk%' OR
            u.last_name LIKE '%desk%'
        )
    ) AND
    a.serial_number LIKE '%%' AND
    a.category_id='2'
LIMIT 25
OFFSET 5450

Comments

0

You are missing the join between the two tables.

Add something like

 AND  a.user_id = u.user_id

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.