Сравнение значений в двух таблицах, сгруппированных по другому значению SQL

#sql #sql-server #inner-join #having-clause #relational-division

#sql #sql-сервер #внутреннее соединение #наличие-предложение #реляционное разделение

Вопрос:

Для того, чтобы пользователь имел доступ к сущности, пользователь должен иметь необходимые классификации, настроенные для него. Классификации имеют несколько атрибутов разных типов атрибутов. Пользователи в равной степени имеют несколько атрибутов. Для того, чтобы пользователь соответствовал требованиям классификации, он должен иметь по крайней мере один атрибут каждого типа, применяемый к классификации.

Итак, из следующих данных

 dbo.Classification
ClassificationID    ClassificatinName
10                  Class1

dbo.Attribute
AttributeID      AttributeName     AttributeTypeID
1                Type1 Attr1       1
2                Type1 Attr2       1
3                Type2 Attr1       2
4                Type2 Attr2       2

dbo.ClassificationAttribute
ClassificationID       AttributeID
10                     1
10                     2
10                     4  

dbo.EntityClassification
EntityID         ClassificationID
100              10

dbo.UserAttribute
UserID                 AttributeID
1000                   1
1000                   4
2000                   2
2000                   3
  

Идентификатор пользователя 1000 должен соответствовать требованиям для ClassificationID 10 и, следовательно, EntityId 100, поскольку у них есть по крайней мере один атрибут каждого типа, настроенный для этой классификации, но пользователь 200 не должен. Данные, которые я хочу в конечном итоге вернуть, будут:

 UserID      EntityID
1000        100
  

Как это можно сделать в SQL?

Комментарии:

1. «Как это лучше всего сделать в SQL?» Это слишком широкий вопрос. В чем заключается ваш конкретный вопрос? Что насчет того, что вы пробовали, не сработало, или почему вы считаете, что это не «лучше»? Что определяет «лучший»?

2. Вы забыли указать нам имена таблиц.

3. Извините, как это можно было сделать, лучше или иначе, это то, что я имел в виду.

Ответ №1:

Я понимаю это как проблему реляционного разделения. Вы можете обратиться к нему с помощью объединений и having предложения для фильтрации:

 select ec.entityid, ua.userid
from entityclassification ec
inner join attribute a1 on a1.attributeid = ec.attributeid
inner join attribute a2 on a2.attriubutetypeid = a1.attriubutetypeid
inner join userattribute ua on ua.attributeid = a2.attributeid
where ec.entityid = 100
group by ec.entityid, ua.userid
having count(distinct a2.attriubutetypeid) = (
    select count(distinct a3.attriubutetypeid)
    from entityclassification ec3
    inner join attribute a3 on a3.attributeid = ec.attributeid
    where ec3.entityid = 100
)
  

В основном это объединяет всех пользователей, чьи атрибуты имеют хотя бы один общий тип с целевой сущностью. Затем предложение having гарантирует, что все типы были сопоставлены.