Модель данных
Из вашего комментария я вижу, что у вас есть другие таблицы свойств, которые вы не упомянули в своем вопросе.Я предполагаю, что мы можем пока игнорировать их и сконцентрироваться на представлении значений свойств, что можно сделать с помощью упрощенной модели, приведенной ниже:
![enter image description here](https://i.stack.imgur.com/GuIjV.png)
DDL SQL (MS SQL Server):
CREATE TABLE [USER] (
USER_ID int NOT NULL,
NICKNAME nvarchar(50) NOT NULL,
CONSTRAINT PK_USER PRIMARY KEY CLUSTERED (USER_ID)
);
CREATE TABLE USER_PROPERTY_VALUE(
USER_ID int NOT NULL,
PROPERTY_NAME nvarchar(50) NOT NULL,
PROPERTY_VALUE_NO int NOT NULL,
PROPERTY_VALUE nvarchar(255) NOT NULL,
CONSTRAINT PK_USER_PROPERTY_VALUE PRIMARY KEY CLUSTERED (
USER_ID,
PROPERTY_NAME,
PROPERTY_VALUE_NO
)
);
ALTER TABLE USER_PROPERTY_VALUE ADD CONSTRAINT FK_USER_PROPERTY_VALUE_USER FOREIGN KEY(USER_ID)
REFERENCES [USER] (USER_ID);
Многозначное значение представлено несколькими строками в USER_PROPERTY_VALUE, совместно использующими одно и то же имя PROPERTY_NAME, но каждая из которых имеет отдельный PROPERTY_VALUE_NO.
Данные следующего примера ...
Rob: HairColor={brown}, Hobby={basketball,football}
Bob: HairColor={brown}, Hobby={basketball}
Steve: Hobby={basketball,football}
... представлен в базе данных следующим образом:
USER:
USER_ID NICKNAME
1 Rob
2 Bob
3 Steve
USER_PROPERTY_VALUE:
USER_ID PROPERTY_NAME PROPERTY_VALUE_NO PROPERTY_VALUE
1 HairColor 1 brown
1 Hobby 1 basketball
1 Hobby 2 football
2 HairColor 1 brown
2 Hobby 1 basketball
3 Hobby 1 basketball
3 Hobby 2 football
Примеры запросов
Выберите пользователей с коричневым цветом волос:
SELECT *
FROM [USER]
WHERE
EXISTS (
SELECT *
FROM USER_PROPERTY_VALUE
WHERE
USER_PROPERTY_VALUE.USER_ID = [USER].USER_ID
AND PROPERTY_NAME = 'HairColor'
AND PROPERTY_VALUE = 'brown'
)
Результат:
USER_ID NICKNAME
1 Rob
2 Bob
Выберите пользователей, увлечения которых включают баскетбол и футбол:
SELECT *
FROM [USER]
WHERE
EXISTS (
SELECT *
FROM USER_PROPERTY_VALUE
WHERE
USER_PROPERTY_VALUE.USER_ID = [USER].USER_ID
AND PROPERTY_NAME = 'Hobby'
AND PROPERTY_VALUE = 'basketball'
)
AND EXISTS (
SELECT *
FROM USER_PROPERTY_VALUE
WHERE
USER_PROPERTY_VALUE.USER_ID = [USER].USER_ID
AND PROPERTY_NAME = 'Hobby'
AND PROPERTY_VALUE = 'football'
)
Результат:
USER_ID NICKNAME
1 Rob
3 Steve
Выберите пользователей, у которых коричневый цвет волос и хобби: баскетбол и футбол.
SELECT *
FROM [USER]
WHERE
EXISTS (
SELECT *
FROM USER_PROPERTY_VALUE
WHERE
USER_PROPERTY_VALUE.USER_ID = [USER].USER_ID
AND PROPERTY_NAME = 'HairColor'
AND PROPERTY_VALUE = 'brown'
)
AND EXISTS (
SELECT *
FROM USER_PROPERTY_VALUE
WHERE
USER_PROPERTY_VALUE.USER_ID = [USER].USER_ID
AND PROPERTY_NAME = 'Hobby'
AND PROPERTY_VALUE = 'basketball'
)
AND EXISTS (
SELECT *
FROM USER_PROPERTY_VALUE
WHERE
USER_PROPERTY_VALUE.USER_ID = [USER].USER_ID
AND PROPERTY_NAME = 'Hobby'
AND PROPERTY_VALUE = 'football'
)
Результат:
USER_ID NICKNAME
1 Rob
И т. Д. И т. Д..
Запросы на основе содержимого другой таблицы
Допустим,у вас есть таблица, содержащая критерии фильтра:
CREATE TABLE PROPERTY_FILTER (
PROPERTY_NAME nvarchar(50) NOT NULL,
PROPERTY_VALUE nvarchar(255) NOT NULL,
CONSTRAINT PK_PROPERTY_FILTER PRIMARY KEY (PROPERTY_NAME, PROPERTY_VALUE)
)
Следующий запрос вернет только тех пользователей, которые соответствуют критериям, которые в настоящее время содержатся в этой таблице:
SELECT *
FROM [USER] U
WHERE
NOT EXISTS (
SELECT F.PROPERTY_NAME, F.PROPERTY_VALUE
FROM PROPERTY_FILTER F
EXCEPT
SELECT P.PROPERTY_NAME, P.PROPERTY_VALUE
FROM USER_PROPERTY_VALUE P
WHERE P.USER_ID = U.USER_ID
)
На простом английском языке: еслиесть свойство фильтра, которое также не является свойством пользователя, игнорируйте этого пользователя.
Кстати, это не будет работать в параллельной многопользовательской среде - вам потребуется ввести дополнительное поле в таблице PROPERTY_FILTER, чтобы определить«сеанс» или используйте временные таблицы (если вам не требуется постоянство).