I wrote a query that searches people based on search parameters from 3 other tables (phones, emails, addresses). I'm pretty sure this is not the most efficient way to do this, any performance tips are greatly appreciated :)
Note that the user may choose to search by less than all the possible criteria, for example search only by phone and email but not by address and name. In such cases a php code will dynamically generate a search query that excludes the unwanted parameters.
SQL
SELECT
id,
name,
group_concat(
DISTINCT concat( number, ' (', phones.description, ')' )
ORDER BY phones.description
SEPARATOR '<br>'
) AS phones,
group_concat(
DISTINCT concat( email, ' (', emails.description, ')' )
ORDER BY emails.description
SEPARATOR '<br>'
) AS emails,
group_concat(
DISTINCT concat( address, ' (', addresses.description, ')' )
ORDER BY addresses.description
SEPARATOR '<br>'
) AS addresses
FROM people
LEFT OUTER JOIN phones
ON phones.person_id = id
LEFT OUTER JOIN emails
ON emails.person_id = id
LEFT OUTER JOIN addresses
ON addresses.person_id = id
WHERE id IN (
SELECT DISTINCT person_id
FROM phones
WHERE number LIKE ?
AND person_id IN (
SELECT DISTINCT person_id
FROM emails
WHERE email LIKE ?
AND person_id IN (
SELECT DISTINCT person_id
FROM addresses
WHERE address LIKE ?
)
)
)
AND name LIKE ?
GROUP BY id
ORDER BY id DESC;
Sample database tables
people:
+----+----------------------+
| id | name |
+----+----------------------+
| 1 | Bob |
| 2 | Daniel |
| 3 | Joe |
| 4 | Some other name |
| 5 | Robby Williams |
+----+----------------------+
phones:
+-----------+------------+-------------+
| person_id | number | description |
+-----------+------------+-------------+
| 1 | 123456789 | home |
| 1 | 123412341 | office |
| 2 | 1234554321 | |
| 3 | 8525824725 | home |
| 3 | 5832593952 | office |
| 3 | 6035262953 | fax |
| 3 | 6832525753 | office 2 |
| 3 | 6735926752 | z |
| 3 | 6830589736 | zz |
| 3 | 2893475979 | zzz |
| 3 | 7823569459 | zzzz |
| 4 | 666 | secretary |
| 4 | 444422220 | office |
| 4 | 111111111 | home |
| 5 | 444422220 | office |
| 5 | 1111111111 | home |
+-----------+------------+-------------+
emails:
+-----------+------------------+-------------+
| person_id | email | description |
+-----------+------------------+-------------+
| 1 | [email protected] | |
| 2 | [email protected] | fake email |
| 3 | [email protected] | |
+-----------+------------------+-------------+
addresses:
+-----------+----------------------------------------------------+-------------+
| person_id | address | description |
+-----------+----------------------------------------------------+-------------+
| 1 | Anywhere | home |
| 1 | Nowhere, apt 2 | work |
| 2 | The Moon | home |
| 2 | Venus | office |
| 3 | 123 something something, apt -2.5 | basement |
| 4 | Hello, apt 26 | |
| 5 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | office |
+-----------+----------------------------------------------------+-------------+
Sample output
For search parameters: [ '%1%', '%fakemail%', '%moon%', '%d%' ]
+----+--------+---------------+-------------------------------+-----------------------------------+
| id | name | phones | emails | addresses |
+----+--------+---------------+-------------------------------+-----------------------------------+
| 2 | Daniel | 1234554321 () | [email protected] (fake email) | The Moon (home)<br>Venus (office) |
+----+--------+---------------+-------------------------------+-----------------------------------+

descriptioncolumns? What do your tables actually look like? The cherry on the pudding would be some example data... \$\endgroup\$LIKEoperator). The user may choose to search by less than all of these parameters, in which case aphpcode will dynamically create a query string that excludes the unwanted search parameters. \$\endgroup\$descriptioncolumns are supposed to contain stuff like "home", "office", "fax", etc. \$\endgroup\$