How can I select all rows in a table a, which have n characteristics given in a table b
I'm making a web page for renting houses.
the publications are stored in a table like this
ta_publications
+---+-------------+------+
|id | 开发者_如何学Pythonname | date |
+---+-------------+------+
| 1 | name_001 | ... |
| 2 | name_002 | ... |
| 3 | name_003 | ... |
+---+-------------+------+
I have diferent publications, which have "features" such as "satellite tv", "Laundry cleaning", etc.
These features might change in the future, and I want to be able to add/remove/modify them, so I store them in the database in a table.
ta_feature_types
+---+-------------+
|id | name |
+---+-------------+
| 1 | Internet |
| 2 | Wi-Fi |
| 3 | satelital tv|
+---+-------------+
which are related to the publications using a table
ta_features
+---+-------------+----------------+
|id | type_id | publication_id |
+---+-------------+----------------+
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 3 | 1 |
+---+-------------+----------------+
I think it's pretty easy to understand; There is a publication called name_001 which have internet, wi-fi and satellite tv.
My problem is: I need to be able to efficiently search and select all publications(houses) wich have certain features. For example, all publications that have internet, wifi and "pets-allowed" features.
I just came up with another question: When the user likes one publication, say "house_003", how do I get a list of the features that it does have?
If you want to get publications by feature name:
SELECT p.*
FROM ta_publications p
JOIN ta_features f ON f.publication_id = p.id
JOIN ta_feature_types t ON f.type_id = t.id
WHERE t.name = ? -- feature name
If you already know the feature ID:
SELECT p.*
FROM ta_publications p
JOIN ta_features f ON f.publication_id = p.id
WHERE f.type_id = ? -- feature ID
EDIT: To get all publications that match all of multiple feature IDs:
SELECT p.id, p.name
FROM pub p
JOIN pub_feat pf ON pf.pub_id = p.id
WHERE pf.feat_id IN ? -- list of feature IDs, e.g. (1,2,3)
GROUP BY p.id, p.name HAVING COUNT(*) = ? -- size of list of feature IDs, e.g. 3
To get all the features (names, I assume) by publication ID:
SELECT t.name
FROM ta_feature_types t
JOIN ta_features f ON f.type_id = t.id
JOIN ta_publications p ON f.publication_id = p.id
WHERE p.id = ? -- publication ID
Some notes on your schema:
As I commented above, you don't need an ID column in the
ta_features
table unless a publication can have the same features multiples times, e.g. "2x Wi-Fi"Your table names are confusing, may I suggest you rename
ta_features
tota_publication_features
(orta_pub_features
) andta_feature_types
tota_features
For performance reasons you should create indices on all the columns used in the above JOIN conditions (using your original table names here):
ta_publications(id)
ta_features(type_id, publication_id)
ta_feature_types(id)
If the user selects multiple features use the IN
keyword and a list of all features for a publication:
SELECT p.*
FROM ta_publications p
WHERE '1' in (select type_id from ta_features where publication_id = p.id)
AND '2' in (select type_id from ta_features where publication_id = p.id)
AND '3' in (select type_id from ta_features where publication_id = p.id)
You could generate the above with a loop in your server language of choice. ie.
SELECT p.*
FROM ta_publications p
WHERE 1=1
//START SERVER LANGUAGE
for (feature in featuresArray){
print("AND '$feature' in (select type_id from ta_features where publication_id = p.id)");
}
//END SERVER LANGUAGE
I think what you want is a subquery:
select a.*
from ta_publications as a
where '1' in (select type_id from ta_features where publication_id=a.id)
Substitute '1' for any other feature number you want.
For your second question. A simple query should do it:
select type_id
from ta_features
where publication_id=[[[id that someone likes]]]
精彩评论