Вот моя проблема. У меня есть many-many таблица, названная 'user_has_personalities'. В моем приложении у пользователей могут быть многие личности, и личность может принадлежать многим пользователям.
Таблица имеет два целочисленных столбца, user_id и personality_id.
То, что я должен сделать, получают всех пользователей, которые имеют по крайней мере все личности (ряд personality_ids переменного размера), который я предоставляю к запросу.
Для примера я хотел бы получить всех пользователей, которые имеют личности с идентификаторами 4, 5, 7, но могут также иметь некоторые другие личности. Но мне нужен запрос для работы на переменное количество требуемых идентификаторов личности, как 4, 5, 7, 9, 10 для примера.
Какие-либо идеи?
Нет такого понятия, как лучшие инструменты, которые можно купить за деньги.
Нет, это эвфемизм для отношения, которое отвергает ложную экономику мириться с низшими инструментами ради подсчета бобов.
-121--1663359-Во-первых, у вас не должно быть полей artist_id и художника. Они строятся из модели. Если вам нужно имя исполнителя, добавьте artist_name поле, то есть CharField .
Кроме того, вы пытаетесь извлечь что-то из cleaned_data внутреннего чистого значения. Могут отсутствовать необходимые данные - следует использовать значения из self.data, где - данные непосредственно из POST.
-121--2053916-Этот запрос выполняет задачу:
select user_id
from user_has_personalities
where personality_id in (<list-of-personality-ids>)
group by user_id
having count(*) = <numer-of-items-in-IN-list>
Необходимо указать разделенный запятыми список идентификаторов личности для < список идентификаторов личности >
, а также указать количество предметов в списке. Придерживаясь своего примера, вы получите:
select user_id
from user_has_personalities
where personality_id in (4,5,7)
group by user_id
having count(*) = 3
это гарантирует, что вы получите только пользователей, которые имеют все эти личности.
SELECT *
FROM (
SELECT DISTINCT user_id
FROM user_has_personalities
) uhpo
WHERE EXISTS
(
SELECT NULL
FROM user_has_personalities uhpi
WHERE uhpi.user_id = uhpo.user_id
AND personality_id IN (4, 5, 6, 9, 10)
LIMIT 1 OFFSET 4
)
Значение смещения должно быть на 1
меньше, чем количество элементов в списке IN
.
Если у вас есть личный список в специальной таблице, используйте это:
SELECT *
FROM (
SELECT DISTINCT user_id
FROM user_has_personalities
) uhpo
WHERE (
SELECT COUNT(*)
FROM perslist p
JOIN user_has_personalities uhpi
ON uhpi.user_id = uhpo.user_id
AND uhpi.personality_id = p.id
) =
(
SELECT COUNT(*)
FROM perslist
)
Чтобы это работало правильно (и быстро), у вас должен быть индекс UNIQUE
для user_has_personalities (user_id , identity_id)
(в таком порядке).
Если у вас есть таблица users
и почти все пользователи имеют запись в user_has_personalities
, то замените ее вложенным запросом DISTINCT
:
SELECT user_id
FROM users uhpo
WHERE (
SELECT COUNT(*)
FROM perslist p
JOIN user_has_personalities uhpi
ON uhpi.user_id = uhpo.user_id
AND uhpi.personality_id = p.id
) =
(
SELECT COUNT(*)
FROM perslist
)
SELECT a.user_id
FROM user_has_personalities a
JOIN user_has_personalities b ON a.user_id = b.user_id AND b.personality_id = 5
JOIN user_has_personalities c ON a.user_id = c.user_id AND b.personality_id = 7
WHERE a.personality_id = 4
Было бы достаточно легко сгенерировать этот список программно, но это не так просто, как предоставить набор. С другой стороны, это работоспособно.