I have two database tables customers which contains data about customers with the scheme like that:
mysql> SELECT * FROM customers; customer_id created_at partner_id 1 "2019-08-20 09:17:58" cats 2 "2019-09-12 11:46:37" dogs
and customers_facts which keeps the customers facts in a form of fact_name and corresponding fact_value.
mysql> SELECT * FROM customers_facts; customer_id fact_name fact_value 1 name Milton 1 city Milan 1 birthday "2019-08-20 09:17:58" 1 company Idaho 2 surname Bloom 2 name Orlando 3 name Milton 3 city Milan 3 birthday "2011-10-20 11:17:58" 3 company Chicago
I want to create a query to get all customer_id where name=Milton and city=Milan sorted by birthday and company. So in my example the results would be:
mysql> SELECT customer_id FROM .... customer_id 1 3
I have a query which gets all the customers_id where name=Milton and city=Milan
SELECT cf.* FROM customers_facts cf
WHERE cf.customer_id IN (
SELECT cf.customer_id FROM customers_facts cf
WHERE (cf.fact_name,cf.fact_value) IN (('name','Milton'),('city','Milan'))
GROUP BY cf.customer_id
HAVING COUNT(*) = 2
)
But I have no idea on how to sort the results by fact_value How to do it ? Is it even possible with such scheme ?
Advertisement
Answer
This is a little tricky. You can’t filter easily before aggregating. So, do the filtering in the having clause:
SELECT customer_id
FROM customers_facts
GROUP BY customer_id
HAVING SUM( fact_name = 'name' AND fact_value = 'Milton' ) > 0 AND
SUM( fact_name = 'city' AND fact_value = 'Milan' ) > 0
ORDER BY MAX(CASE WHEN fact_name = 'birthday' THEN fact_value END) DESC,
MAX(CASE WHEN fact_name = 'company' THEN fact_value END)