расстояние между данным набором и некоторыми другими наборами - sql server 2005 - PullRequest
0 голосов
/ 03 февраля 2012

У меня есть таблица, которая содержит идентификаторы товара и категории:

create table SomeTable (
    ItemId int,
    CategoryId int
)

Учитывая некоторые идентификаторы категорий (Set X), я хотел бы определить все идентификаторы элементов, которые имеют хотя бы один идентификатор категории, и некоторые характеристики для каждого из этих идентификаторов элементов:

A - Количество идентификаторов категорий идентификатора элемента, которых нет в наборе x
B - Количество идентификаторов категорий, общих для идентификатора элемента и установленного x
C - Количество идентификаторов категорий в наборе x, но не связанных с идентификатором элемента

Я написал некоторый код tsql, который включает перекрестное соединение и несколько ctes плюс левые соединения. Это работает, но довольно медленно.

Я уверен, что кто-то столкнулся с подобной проблемой. Я хотел бы предоставить код, но приведенное выше описание упрощено. Спасибо.

Ответы [ 2 ]

1 голос
/ 03 февраля 2012

Проблема с CTE состоит в том, что они запускаются каждый раз, когда на них ссылаются, и у них нет ограничений. Загрузите ваш Set X во временную таблицу с первичным ключом по ID. Затем запустите те же соединения против временного, и вы увидите большой прирост производительности. SQL работает намного лучше, когда объединения основаны на первичных ключах.

1 голос
/ 03 февраля 2012

Вот пара идей. (Я не знаю, как они будут сравнивать производительность по сравнению с тем, что у вас уже есть. Оставлено для сравнения.)

set nocount on;

-- create a sample table
declare @T table ( ItemId int identity(1,1), CategoryId int );
insert @T values ( 100 );
insert @T values ( 100 );
insert @T values ( 100 );
insert @T values ( 100 );
insert @T values ( 100 );
insert @T values ( 200 );
insert @T values ( 200 );
insert @T values ( 300 );
insert @T values ( 300 );
insert @T values ( 300 );
insert @T values ( 300 );
insert @T values ( 500 );
insert @T values ( 500 );
insert @T values ( 500 );
insert @T values ( 600 );
insert @T values ( 700 );
insert @T values ( 800 );
insert @T values ( 800 );
insert @T values ( 800 );
insert @T values ( 900 );


-- grab some CategoryIDs to work with
declare @X table ( CategoryId int );
insert @X
    select CategoryID=200 union
    select CategoryID=400 union
    select CategoryID=600 union
    select CategoryID=800 


-- A. Number of category ids of item id that are not in set x
select distinct t.CategoryID from @T t
where not exists(select 1 from @X x where t.CategoryID = x.CategoryID)

-- or, using the set difference operator
select CategoryID from @T
except
select CategoryID from @X


-- B. Number of category ids shared between item id and set x
select distinct x.CategoryID from @X x
join @T t on t.CategoryID = x.CategoryID;

-- or, using set intersection
select CategoryID from @T
intersect
select CategoryID from @X


-- C. Number of category ids in set x but which are not associated with item id 
select distinct x.CategoryID from @X x
where not exists(select 1 from @T t where t.CategoryID = x.CategoryID)

-- or, using the set difference operator
select CategoryID from @X
except
select CategoryID from @T
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...