Reputation: 89
I'm struggling with the following thing: I have a table called custom_fields. Within it there is a field with values like product_id, money_spent. When I do an AND query to get data I get 0 results (even though the conditions are met). This is the query:
SELECT DISTINCT `users` . *
FROM `users`
LEFT JOIN `emails` ON `users`.`id` = `emails`.`user_id`
LEFT JOIN `phones` ON `users`.`id` = `phones`.`user_id`
LEFT JOIN `trackers` ON `users`.`tracker_id` = `trackers`.`id`
LEFT JOIN `custom_fields` ON `users`.`id` = `custom_fields`.`user_id`
WHERE (
`custom_fields`.`field` = "product_id"
AND `custom_fields`.`value` IS NOT NULL
AND `custom_fields`.`value` != ""
)
AND (
`custom_fields`.`field` = "payment_value"
)
AND (
`custom_fields`.`value` <50
AND `custom_fields`.`value` IS NOT NULL
AND `custom_fields`.`value` != ""
)
AND (
`users`.`tracker_id` =186
)
How to solve this problem? I tried to use UNION but it gives different results. Maybe some aliases? I can't do the transposition on this table (meaning: convert each row to a seperate field)
Upvotes: 0
Views: 55
Reputation: 94913
All you seem to want to do is select users for which a product id exists and also a payment value less than 50 exists. So simply use the word EXISTS (that one uses to formulate the task) in your query as well and there are no longer issues with duplicate results. Plus the query is much easier to read, because you use SQL straight-forward.
select *
from users
where tracker_id = 186
and exists
(
select *
from custom_fields
where field = 'product_id' and value is not null
)
and exists
(
select *
from custom_fields
where field = 'payment_value' and value < 50 -- and value > 0 maybe?
);
As you see, quite often you can just put the task in words that can be easily translated into SQL.
Please also read in your request's comment section about problems with your query.
Upvotes: 1
Reputation: 2668
Supposing that custom_fields
is a EAV-style table (i.e. it has multiple entries per one entity like user, in form of a set [entry type, entry label, entry value]), you need to do multiple JOIN
s with this table to achieve the desired result.
Try this query instead. It filters users having both: entries in custom_fields
of type product_id
and entries of type payment_value
with value lower than 50:
SELECT DISTINCT `users` . *
FROM `users`
LEFT JOIN `emails` ON `users`.`id` = `emails`.`user_id`
LEFT JOIN `phones` ON `users`.`id` = `phones`.`user_id`
LEFT JOIN `trackers` ON `users`.`tracker_id` = `trackers`.`id`
LEFT JOIN `custom_fields` as cf1 ON `users`.`id` = cf1.`user_id`
LEFT JOIN `custom_fields` as cf2 ON `users`.`id` = cf2.`user_id`
WHERE (
cf1.`field` = "product_id"
AND cf1.`value` IS NOT NULL
AND cf1.`value` != ""
)
AND (
cf2.`field` = "payment_value"
AND cf2.`value` <50
AND cf2.`value` IS NOT NULL
AND cf2.`value` != ""
)
AND (
`users`.`tracker_id` =186
)
Upvotes: 1
Reputation: 56
May be can try using self join / or creating aliases of custom_fields table. Try below query
SELECT DISTINCT `users` . *
FROM `users`
LEFT JOIN `emails` ON `users`.`id` = `emails`.`user_id`
LEFT JOIN `phones` ON `users`.`id` = `phones`.`user_id`
LEFT JOIN `trackers` ON `users`.`tracker_id` = `trackers`.`id`
LEFT JOIN `custom_fields` cf1 ON `users`.`id` = `cf1`.`user_id`
LEFT JOIN `custom_fields` cf2 ON `users`.`id` = `cf2`.`user_id`
WHERE (
`cf1`.`field` = "product_id"
AND `cf1`.`value` IS NOT NULL
AND `cf1`.`value` != ""
)
AND (
`cf2`.`field` = "payment_value"
)
AND (
`cf2`.`value` <50
AND `cf2`.`value` IS NOT NULL
AND `cf2`.`value` != ""
)
AND (
`users`.`tracker_id` =186
)
Upvotes: 0