I need some help on a MySQL query I'm trying to set up. I need to find records that match conditions that are located in two different tables with a many to many relationship.
I use three tables in this query, the first contains projects, the second contains topics and the third ties them together. I want the query to find projects that are related to the topic that was selected by the user. Users can also select more than one topic to perform th开发者_JAVA百科e search. In that case I only want to show projects that are related to both topics and not to either of them. This is what I can't figure out how to do. I expected that I'd have to do something like this but this query yields no results whilst there is a project that is linked to both topics in the database.
SELECT `projects`.*
FROM `projects`, `topics`, `projects_topics`
WHERE (`name` LIKE '%%' || `vision` LIKE '%%' || `highlights` LIKE '%%' || `optional` LIKE '%%')
&& ((`projects_topics`.`projects_id` = `projects`.`id` && `projects_topics`.`topics_id` = `topics`.`id` && `topics`.`id` = '1')
&& (`projects_topics`.`projects_id` = `projects`.`id` && `projects_topics`.`topics_id` = `topics`.`id` && `topics`.`id` = '9'))
ORDER BY `date_added` DESC
These are the tables:
projects
+--------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| fields_id | int(11) | NO | PRI | NULL | |
| name | varchar(255) | YES | | NULL | |
| address | varchar(255) | YES | | NULL | |
| zip | varchar(255) | YES | | NULL | |
| city | varchar(255) | YES | | NULL | |
| state | varchar(255) | YES | | NULL | |
| countries_id | int(11) | NO | PRI | NULL | |
| website | varchar(255) | YES | | NULL | |
| client | varchar(255) | YES | | NULL | |
| finished | date | YES | | NULL | |
| budget | int(11) | YES | | NULL | |
| vision | text | YES | | NULL | |
| highlights | text | YES | | NULL | |
| innovation | text | YES | | NULL | |
| optional | text | YES | | NULL | |
| publish | tinyint(1) | YES | | NULL | |
| date | datetime | YES | | NULL | |
| featured | tinyint(1) | YES | | NULL | |
| frontpage | tinyint(1) | YES | | NULL | |
| date_added | datetime | YES | | NULL | |
+--------------+--------------+------+-----+---------+----------------+
topics
+-------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| topic | varchar(255) | YES | | NULL | |
| order | int(11) | YES | | NULL | |
+-------+--------------+------+-----+---------+----------------+
projects_topics
+-------------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+---------+------+-----+---------+-------+
| projects_id | int(11) | NO | PRI | NULL | |
| topics_id | int(11) | NO | PRI | NULL | |
+-------------+---------+------+-----+---------+-------+
SELECT p.*
FROM (
SELECT project_id
FROM project_topics pt
WHERE topics_id IN (5, 9)
GROUP BY
project_id
HAVING COUNT(*) = 2
) pto
JOIN projects p
ON p.project_id = pto.project_id
or
SELECT p.*
FROM projects p
WHERE EXISTS
(
SELECT NULL
FROM project_topics pt
WHERE pt.project_id = p.project_id
AND pt.topic_id IN (5, 9)
LIMIT 1 OFFSET 1
)
Make sure that the PK
in project_topics
is defined as (project_id, topic_id)
(in this order), or create an additional UNIQUE
index on (topic_id, project_id)
.
精彩评论