I am getting completely crazy with this query and was wondering if there is a genius out there for whom this would be a mere child’s play…?
This query should suggest random users to logged in users, whereas the relationship between the logged-in user and the suggested users must not be blocked in one of those ways:
- by continents
- by countries
- by age-range
- by gender
- by id (blocker<->blockee)
Table structure
user
id | username | country_id_home | timestamp_lastonline | gender | birthdate | allow_gender | age_min | age_max | ...
comment: birthdate is in mysql-date format (YYYY-MM-DD), gender (0=female,1=male), allow_gender (0=both, 1=female, 2=male)
countries
country_id | name | continent_id | ...
cities
id | city_real | ...
comment: loc_id_home in table user matches id in cities
blocked_countries
id | user_id | country_id | ...
blocked_continents
id | user_id | continent_id | ...
blocked_user
id | user1_id | user2_id | ...
comment: user1 is “blocker”, user2 is “blockee”
The query I have till now is:
SELECT u.id AS user_id, u.username, u.fname, u.country_id_home, u.timestamp_reg, u.timestamp_upd, u.timestamp_lastonline, u.online_status, u.gender, u.birthdate, u.prof_pic,
(SELECT name FROM countries co WHERE co.country_id=u.country_id_home) AS country_name,
(SELECT city_real FROM cities ci WHERE ci.id=u.loc_id_home) AS city ,
(SELECT region_name FROM regions r WHERE r.id=u.region_id_home) AS region,
(SELECT region_short FROM regions r WHERE r.id=u.region_id_home) AS region_short
FROM user_d1 u
LEFT JOIN (
SELECT DISTINCT user2_id AS blockee_id
FROM blocked_user
WHERE user1_id = :user1_id1
)this_user_blocked ON u.id = this_user_blocked.blockee_id
LEFT JOIN (
SELECT DISTINCT user1_id AS blocker_id
FROM blocked_user
WHERE user2_id = :user1_id2
)blocked_this_user ON u.id = blocked_this_user.blocker_id
WHERE
(allow_gender=0 OR allow_gender=:user1_allow_gender)
AND age_min<=:user1_age1
AND age_max>=:user1_age2
AND prof_status<>2
AND this_user_blocked.blockee_id IS NULL AND blocked_this_user.blocker_id IS NULL
AND NOT EXISTS (SELECT 1 FROM blocked_countries bc WHERE bc.user_id=u.id AND bc.country_id =:user1_country)
AND NOT EXISTS (SELECT 1 FROM blocked_countries bc WHERE bc.user_id=:user1_id3 AND bc.country_id = u.country_id_home)
AND EXISTS (
SELECT 1 FROM user_d1 u2
WHERE u2.id=:user1_id4
AND (u2.allow_gender=0 OR u2.allow_gender=(u.gender+1))
AND age_min<=(DATEDIFF(NOW(),u.birthdate))
AND age_max>=(DATEDIFF(NOW(),u.birthdate))
AND prof_status<>2
)
LIMIT 0,6
Without the last AND EXISTS... the result set is not empty, however like this it does always return no results. Yet blocked by continents is not included and it is not yet ordered by timestamp_lastonline…
What am I doing wrong in the last AND EXISTS...? Should it rather be done with a JOIN? I’ve tried that too, but it gave an empty result as well…
I have stored all necessary variables from the logged in user in SESSION-variables… if you find anything else in the query that could be done in a better way I’d be very happy for your help too!
Thank you very much in advance!
I think it’s because of
DATEDIFF, which returns the numbers of days between two dates and not the number of years. ThereforeDATEDIFFis probably always greater than age_max.EDIT: You could do something like this instead: