Re: найти все комбинации
От: Flying Dutchman Украина  
Дата: 05.10.07 12:06
Оценка:
Здравствуйте, ., Вы писали:

.>Как такой запрос сфарганить?

.>table Sale(id)
.>table SaleItem(saleId, productId)
.>нужно выбрать все возможные комбинации productId для всех Sale.
.>­Т.е. скажем
.>Sale(1), у него SaleItem(1, 10), SaleItem(1, 11)
.>Sale(2), у него SaleItem(2, 10), SaleItem(2, 11)
.>Sale(3), у него SaleItem(3, 10), SaleItem(3, 11), SaleItem(3, 12)
.>Sale(4), у него SaleItem(4, 10), SaleItem(4, 13)
.>Здесь есть всего 3 комбинации продуктов [10,11], [10,11,12] и [10,13].

.>По моим ожиданиям комбинаций должно быть несколько десятков, а продаж —

.>сотни тысяч.
.>mssql 2000, если это имеет значение. Хотя хочется знать более менее
.>универсальное решение.

Интересная головоломка. Для ее решения можно использовать
реляционное деление без остатка.

Сначала создадим таблицу и заполним ее данными.

create table SaleItem(
  SaleId    int not null,
  ProductId int not null,
  primary key(SaleId, ProductId))

insert into SaleItem(SaleId, ProductId) values(1, 10)
insert into SaleItem(SaleId, ProductId) values(1, 11)
insert into SaleItem(SaleId, ProductId) values(2, 10)
insert into SaleItem(SaleId, ProductId) values(2, 11)
insert into SaleItem(SaleId, ProductId) values(3, 10)
insert into SaleItem(SaleId, ProductId) values(3, 11)
insert into SaleItem(SaleId, ProductId) values(3, 12)
insert into SaleItem(SaleId, ProductId) values(4, 10)
insert into SaleItem(SaleId, ProductId) values(4, 13)
insert into SaleItem(SaleId, ProductId) values(5, 10)
insert into SaleItem(SaleId, ProductId) values(5, 11)
insert into SaleItem(SaleId, ProductId) values(5, 12)
insert into SaleItem(SaleId, ProductId) values(6, 10)
insert into SaleItem(SaleId, ProductId) values(6, 13)


Теперь выполним запрос

select SaleId, ProductId
  from SaleItem as s0
  where not exists (
        select s1.SaleId
        from SaleItem as s1 left outer join
                (select ProductId
                 from SaleItem
                 where SaleId = s0.SaleId) as s2
              on s1.ProductId = s2.ProductId
        where s1.SaleId < s0.SaleId
        group by s1.SaleId
        having count(s1.ProductId) = (select count(*)
                           from SaleItem
                           where SaleId = s0.SaleId) and
               count(s2.ProductId) = (select count(*)
                           from SaleItem
                           where SaleId = s0.SaleId)
        )


Результат запроса будет таким:

1 10
1 11
3 10
3 11
3 12
4 10
4 13

Для каждой повторяющейся комбинации продуктов оставлена одна комбинация
с минимальным SaleId.

Запрос не самый эффективный, но его можно оптимизировать.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.