The Schema:
I have 3 Tables:
- User
- Feature
- User_has_Feature:
initially all users has no features
Example data:
User:
| id | name |
| 1 | Rex |
| 2 | Job |
Feature:
| id | name |
| 1 | Eat |
| 2 | Walk |
User_has_Feature:
| id | user_id | feature_id | have_feature |
| 1 | 1 | 1 | true |
| 2 | 1 | 1 | true |
| 3 | 2 | 2 | true |
| 4 | 2 | 2 | false |
The questions are:
- ¿How to get only the records that have all features? (explicitly)
Example:
| user_name | feature_name | feature_status |
| Rex | Eat | true |
| Rex | Walk | true |
- How to get records that do not have all the features? (again explicitly)
Example:
| user_name | feature_name | feature_status |
| Job | Eat | true |
| Job | Walk | false |
Some conditions have to be attended
- I need the Users list with all features (true or false) in both queries like examples
- User have 650k records (for now)
- Feature have 45 records (for now)
- Is one time query.
The idea is to export the result to a CSV file
Early Solution
thanks to the answers of (@RolandoMySQLDBA, @Tom Ingram, @DRapp) I found a solution:
SELECT u.name, f.name, IF(uhf.status=1,'YES','NO') as status
FROM user u
JOIN user_has_feature uhf ON u.id = uhf.user_id
JOIN feature f ON f.id = uhf.feature_id
JOIN
(
SELECT u.id as id
FROM user u
JOIN user_has_feature uhf ON uhf.user_id = u.id
WHERE uhf.status = 1
GROUP BY u.id
HAVING count(u.id) <= (SELECT COUNT(1) FROM feature)
) as `condition` ON `condition`.id = u.id
ORDER BY u.name, f.id, uhf.status
For get records that do not have all the features and for get all record that have all features change:
WHERE uhf.status = 1byWHERE uhf.status = 2HAVING count(u.id) <= (SELECT COUNT(1) FROM feature)byHAVING count(u.id) = (SELECT COUNT(1) FROM feature)
but I want to know if this is an optimal solution?
The UNF subquery returns with all users listed in User_has_Feature and a comma-separated list of the features. The column
HasAllFeaturesis determined by the number of columns inUNF.FeatureList. In your case, there are two features. If the number of commas in UNF.FeatureList is FeatureCount – 1, then the user has all features. Otherwise, user does not have all features.Here is a better version that shows all users and whether or not they have all, some or no features