Ваше лучшее решение - вернуться к традиционному столу, потому что EAV делает большинство запросов намного сложнее, чем должно быть - засвидетельствуйте ваши проблемы здесь.Вы будете выполнять самостоятельные объединения, пока не устанете от них, и восстановите структуру таблицы, которая позволит вам выполнять разумные запросы.
Города и страны для каждого идентификатора пользователя:
SELECT a.userID, a.value AS city, b.value AS country
FROM EAV AS a
JOIN EAV AS b ON a.UserID = b.UserID
WHERE a.key = 'city'
AND b.key = 'country';
Итак, вы получите:
SELECT city, country, count(*)
FROM (SELECT a.userID, a.value AS city, b.value AS country
FROM EAV AS a
JOIN EAV AS b ON a.UserID = b.UserID
WHERE a.key = 'city'
AND b.key = 'country'
) AS c
GROUP BY city, country;
Если есть вероятность, что у кого-то может быть две записи о городе или двух странах, это даст вам декартово произведение с таким количеством строк для этого пользователя, какпроизведение количества записей о городе и стране для этого пользователя.
Это совершенно сознательно и сознательно игнорирует пользователей, у которых есть город, и нет страны, или страны, и города (не говоря уже о тех, у кого их нет).Расширение решения для решения этих проблем является лишь умеренно болезненным - я полагаю, что в конечном итоге вы получите трехсторонний UNION, хотя, возможно, вам удастся придумать что-то с помощью нескольких левых внешних объединений.Но тот факт, что данные могут быть введены в систему EAV без необходимых ограничений для обеспечения наличия города и страны для пользователя, является просто одной из многих причин отказа от EAV.
Извинитеты навязал это тебе.Я рекомендую смотреть на http://careers.stackoverflow.com/ как на выход из вашей боли, потому что это только начало.
Работа с пользователями, не имеющими ни города, ни страны, ни обоих.Я думаю, что это более или менее сделает это:
SELECT a.userID, b.value AS city, c.value AS country
FROM (SELECT DISTINCT UserID FROM EAV) AS a
LEFT JOIN EAV AS b ON a.UserID = b.UserID
LEFT JOIN EAV AS c ON a.UserID = c.UserID
WHERE b.key = 'city'
AND c.key = 'country';
Это должно дать вам одну запись на пользователя, если для этого пользователя нет нескольких записей о городе или стране.Сканирование a
дает список уникальных идентификаторов пользователей, которые существуют в таблице EAV;два внешних соединения дают вам соответствующий город или города и соответствующую страну или страны для каждого такого идентификатора пользователя, при этом генерируются пустые значения, если для данного идентификатора пользователя нет записи о городе или записи о стране (или обоих).