Reputation: 83
I've had a look around and I have found a few questions like mine but they lack an explanation.
I'm trying to search a table with multiple columns. I want to have the rows with the highest number of match columns at the top and the ones with the least at the bottom. I've seen a few ways of doing. My current and awful way is with lots of MySQLs querys and PHP doing the work.
Example
+----+-----------+----------+------+-------+
| ID | firstName | lastName | more | stuff |
+----+-----------+----------+------+-------+
| 1 | Bob | Hope | 1 | 450 |
| 2 | Steve | Hope | 0 | 29 |
| 3 | Gary | Flops | 1 | 8 |
+----+-----------+----------+------+-------+
I want to be able to search for lastName = Hope OR more = 1
I would like Bob Hope to be at the top because he matches two of the requested things. I know in this example this is what will happen but this is just an example.
If I query; lastName = Hope OR firstName = Steve
. Steve should be at the top followed by Bob
I hope this is easy to understand. Can some give me a detailed example with explanation.
Upvotes: 2
Views: 267
Reputation: 115520
Besides Mike's great answer, here's another option:
SELECT
id,
firstName,
lastName,
more,
stuff,
COUNT(m1.id) + COUNT(m2.id)
AS weight
FROM
mytable AS m
LEFT JOIN
mytable AS m1
ON m1.id = m.id
AND m1.lastName = 'Hope'
LEFT JOIN
mytable AS m2
ON m2.id = m.id
AND m2.firstName = 'Steve'
GROUP BY m.id
HAVING COUNT(m1.id) + COUNT(m2.id) > 0
ORDER BY weight DESC;
and one more:
SELECT
m.id,
m.firstName,
m.lastName,
m.more,
m.stuff,
COUNT(*) AS weight
FROM
mytable AS m
JOIN
( SELECT id
FROM mytable
WHERE lastName = 'Hope'
UNION ALL
SELECT id
FROM mytable
WHERE firstName = 'Steve'
) AS c
ON c.id = m.id
GROUP BY m.id
ORDER BY weight DESC;
Upvotes: 1
Reputation: 21659
How about this:
SELECT
id,
firstName,
lastName,
more,
stuff,
(lastName = 'Hope') + (firstName = 'Steve') AS weight
FROM mytable
ORDER BY weight DESC;
Result:
+----+-----------+----------+------+-------+--------+
| id | firstName | lastName | more | stuff | weight |
+----+-----------+----------+------+-------+--------+
| 2 | Steve | Hope | 0 | 29 | 2 |
| 1 | Bob | Hope | 1 | 450 | 1 |
| 3 | Gary | Flops | 1 | 8 | 0 |
+----+-----------+----------+------+-------+--------+
Upvotes: 5
Reputation: 43219
The easiest way I can think of is with MATCH() ... AGAINST
. You can sort by "score".
SELECT ID, firstName, LastName, stuff, more, MATCH(firstName,LastName,more,stuff) AGAINST ('words to search for' IN BOOLEAN MODE) AS score
FROM yourTable
WHERE MATCH(firstName,LastName,more,stuff) AGAINST ('words to search for' IN BOOLEAN MODE)
ORDER BY score
Problem with this is that it will be slow without a fulltext index and a fulltext index is only available with MyISAM engine.
Upvotes: 1