Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 Пересечение списков  [new]
Rubin_Attack
Member

Откуда:
Сообщений: 64
Доброго времени суток, уважаемые.
Подсобите с запросом, плз, что-то не соображу!

Итак, есть таблица Goods с 2 столбцами Name и CategoryId, то есть товар и его категория, с записями типа:

Товар1 Категория1
Товар1 Категория2
Товар1 Категория3
Товар2 Категория2
Товар3 Категория1
Товар3 Категория3


И есть 2 других таблицы CategoriesList1 и CategoriesList2 у каждой всего один столбец ID.
Пример данных:

CategoriesList1:
Категория1
Категория2

CategoriesList2:
Категория3

Нужно выбрать из таблицы Goods имя товара, который относится как к категориям из таблицы CategoriesList1 так и к категориям из CategoriesList2. Ну то есть, если исходить из наших данных, то подходит только Товар1.
Хелп, плз!!
25 апр 14, 16:42    [15936933]     Ответить | Цитировать Сообщить модератору
 Re: Пересечение списков  [new]
_human
Member

Откуда:
Сообщений: 560
Rubin_Attack,

EXISTS
25 апр 14, 16:45    [15936955]     Ответить | Цитировать Сообщить модератору
 Re: Пересечение списков  [new]
Кавказ-сила
Member

Откуда: Москва
Сообщений: 261
select Name from (
select distinct g.Name from Goods g join CategoriesList1 l on l.Id = g.CategoryId
union all
select distinct g.Name from Goods g join CategoriesList2 l on l.Id = g.CategoryId
) t group by Name having count(*) = 2
25 апр 14, 16:57    [15937065]     Ответить | Цитировать Сообщить модератору
 Re: Пересечение списков  [new]
Rubin_Attack
Member

Откуда:
Сообщений: 64
_human, нельзя ли примерный запрос? про exists знаю, как его тут применить?
25 апр 14, 17:06    [15937130]     Ответить | Цитировать Сообщить модератору
 Re: Пересечение списков  [new]
Rubin_Attack
Member

Откуда:
Сообщений: 64
Кавказ-сила, нет, таким запросом не обойтись. Представьте, что есть товар, у которого 2 категории и обе эти категории относятся к списку1, но у товара нет ни одной из категорий из списка2. Ваш запрос с подсчётом Count(*)=2 здесь сработает
25 апр 14, 17:16    [15937209]     Ответить | Цитировать Сообщить модератору
 Re: Пересечение списков  [new]
_human
Member

Откуда:
Сообщений: 560
Rubin_Attack,

Нужно что бы товар имел обязательно все категории списка 1 и списка2 ?
25 апр 14, 17:19    [15937228]     Ответить | Цитировать Сообщить модератору
 Re: Пересечение списков  [new]
Rubin_Attack
Member

Откуда:
Сообщений: 64
Кавказ-сила, а хотя нет, у вас же distinct, прошу прощения. Да, наверное будет работать, сейчас проверю. Интересно, есть ли варианты проще..
25 апр 14, 17:20    [15937238]     Ответить | Цитировать Сообщить модератору
 Re: Пересечение списков  [new]
Rubin_Attack
Member

Откуда:
Сообщений: 64
_human, нет, не обязательно. хотя бы одну из категории 1 и хотя бы одну из категории 2.
25 апр 14, 17:20    [15937246]     Ответить | Цитировать Сообщить модератору
 Re: Пересечение списков  [new]
Кавказ-сила
Member

Откуда: Москва
Сообщений: 261
Rubin_Attack
Представьте, что есть товар, у которого 2 категории и обе эти категории относятся к списку1
distinct
25 апр 14, 17:21    [15937248]     Ответить | Цитировать Сообщить модератору
 Re: Пересечение списков  [new]
lioner
Member

Откуда: Донецк
Сообщений: 192
Кавказ-сила
select Name from (
select distinct g.Name from Goods g join CategoriesList1 l on l.Id = g.CategoryId
union all
select distinct g.Name from Goods g join CategoriesList2 l on l.Id = g.CategoryId
) t group by Name having count(*) = 2

Этот запрос вернет Товар1 и Товар3.
Поправка:
select Name
from
(
select distinct g.Name from Goods g join CategoriesList1 l on l.Id = g.CategoryId
union all
select distinct g.Name from Goods g join CategoriesList2 l on l.Id = g.CategoryId
) t
group by Name
having count(*) =
(
 select count(*)
 from
 (
  select id
  from CategoriesList1
  union
  select id
  from CategoriesList2
 ) tc
)
25 апр 14, 17:33    [15937326]     Ответить | Цитировать Сообщить модератору
 Re: Пересечение списков  [new]
_human
Member

Откуда:
Сообщений: 560
Rubin_Attack
хотя бы одну из категории 1 и хотя бы одну из категории 2.

тогда результатом будет
Товар1
Товар3
25 апр 14, 17:37    [15937360]     Ответить | Цитировать Сообщить модератору
 Re: Пересечение списков  [new]
lioner
Member

Откуда: Донецк
Сообщений: 192
Rubin_Attack, вы определитесь с постановкой задачи.
25 апр 14, 17:39    [15937372]     Ответить | Цитировать Сообщить модератору
 Re: Пересечение списков  [new]
Rubin_Attack
Member

Откуда:
Сообщений: 64
_human, ух чёрт! так спешил, что еще и результат неточный написал! Конечно же, вы совершенно правы!
25 апр 14, 17:39    [15937379]     Ответить | Цитировать Сообщить модератору
 Re: Пересечение списков  [new]
Rubin_Attack
Member

Откуда:
Сообщений: 64
lioner, должен вернуть Товар1 и Товар3, это я ошибся в описании результата!
25 апр 14, 17:41    [15937388]     Ответить | Цитировать Сообщить модератору
 Re: Пересечение списков  [new]
_human
Member

Откуда:
Сообщений: 560
lioner
select Name
from
(
select g.Name from Goods g join CategoriesList1 l on l.Id = g.CategoryId
union all
select g.Name from Goods g join CategoriesList2 l on l.Id = g.CategoryId
) t
group by Name
having count(*) =
(
 select count(*)
 from
 (
  select id
  from CategoriesList1
  union
  select id
  from CategoriesList2
 ) tc
)


без distinct то что нужно ))
25 апр 14, 17:42    [15937393]     Ответить | Цитировать Сообщить модератору
 Re: Пересечение списков  [new]
lioner
Member

Откуда: Донецк
Сообщений: 192
select distinct Name
from Goods 
where 
CategoryId in (select id from CategoriesList1)
and 
CategoryId in (select id from CategoriesList2)
25 апр 14, 17:46    [15937415]     Ответить | Цитировать Сообщить модератору
 Re: Пересечение списков  [new]
_human
Member

Откуда:
Сообщений: 560
Rubin_Attack,

шота не идет в птн

select sq.name, sum(c1), sum(c2)
from
(
	select g.Name, g.CategoryId
	, case when exists (select * from CategoriesList1 cl1 where g.CategoryId = cl1.Id) then 1 else 0 end  as c1
	, case when exists (select * from CategoriesList2 cl2 where g.CategoryId = cl2.Id) then 1 else 0 end  as c2
	from Goods g
) sq
group by sq.name
having sum(c1) > 0 and sum(c2) > 0
25 апр 14, 17:46    [15937419]     Ответить | Цитировать Сообщить модератору
 Re: Пересечение списков  [new]
lioner
Member

Откуда: Донецк
Сообщений: 192
select distinct g.Name
from Goods g
where 
exists (select * from CategoriesList1 cl where g.CategoryId=cl.id)
and 
exists (select * from CategoriesList2 cl where g.CategoryId=cl.id)
25 апр 14, 17:53    [15937458]     Ответить | Цитировать Сообщить модератору
 Re: Пересечение списков  [new]
_human
Member

Откуда:
Сообщений: 560
_human,

select sq.name
from
(
	select g.Name, g.CategoryId, 'c1' as c
	from Goods g
		join CategoriesList1 cl1 on g.CategoryId = cl1.Id
	union all
	select g.Name, g.CategoryId, 'c2'
	from Goods g
		join CategoriesList2 cl2 on g.CategoryId = cl2.Id
) sq
group by sq.name
having count(distinct sq.c) > 1		
25 апр 14, 18:01    [15937500]     Ответить | Цитировать Сообщить модератору
 Re: Пересечение списков  [new]
lioner
Member

Откуда: Донецк
Сообщений: 192
Rubin_Attack, запрос от 17:46 вам подходит ?
25 апр 14, 18:10    [15937547]     Ответить | Цитировать Сообщить модератору
 Re: Пересечение списков  [new]
Rubin_Attack
Member

Откуда:
Сообщений: 64
lioner, если вы про ваш запрос
select distinct Name
from Goods 
where 
CategoryId in (select id from CategoriesList1)
and 
CategoryId in (select id from CategoriesList2)

то нет. Он пустой результат выдаст. Поскольку он одну и ту же категорию из Goods будет искать сначала в списке 1 а потом в списке 2.
25 апр 14, 18:15    [15937575]     Ответить | Цитировать Сообщить модератору
 Re: Пересечение списков  [new]
Rubin_Attack
Member

Откуда:
Сообщений: 64
_human, да, это работает, спасибо, задачу я с помощью этого решу! Но я вот всё размышляю, неужто нельзя как-то поэлегантнее что ли. А то union с подсчётом кол-ва режет как-то глаз..
25 апр 14, 18:21    [15937608]     Ответить | Цитировать Сообщить модератору
 Re: Пересечение списков  [new]
_human
Member

Откуда:
Сообщений: 560
Rubin_Attack,

	select g.Name
	from Goods g
		left join (select *, 'c1' as c from CategoriesList1) cl1 on g.CategoryId = cl1.Id
		left join (select *, 'c2' as c from CategoriesList2) cl2 on g.CategoryId = cl2.Id
	group by g.Name
	having count(distinct isnull(cl1.c, cl2.c)) > 1
25 апр 14, 18:34    [15937673]     Ответить | Цитировать Сообщить модератору
 Re: Пересечение списков  [new]
Bator
Member

Откуда: Порт пяти морей
Сообщений: 439
-- первый вариант
select distinct
    g.Name
from Goods as g
cross apply(
  select top 1 1
  from CategoriesList1 as l1
  where l1.ID = g.CategoryID 
) as l1
cross apply(
  select top 1 1
  from Goods as x
  join CategoriesList2 as l2 on l2.ID = x.CategoryID
  where x.Name = g.Name 
) as l2

-- первый вариант
select distinct
    g.Name
from Goods as g
where exists(
        select 1
        from CategoriesList1 as l1
        where l1.ID = g.CategoryID 
      ) 
 and  exists(
        select 1
        from Goods as x
        join CategoriesList2 as l2 on l2.ID = x.CategoryID
        where x.Name = g.Name
      )     
25 апр 14, 18:46    [15937750]     Ответить | Цитировать Сообщить модератору
 Re: Пересечение списков  [new]
lioner
Member

Откуда: Донецк
Сообщений: 192
select g.Name
from Goods g join
(
 select id,1 as a
 from CategoriesList1
 union
 select id,2 as a
 from CategoriesList2
) t on g.CategoryId = t.id
group by g.Name
having count(distinct t.a)>1
25 апр 14, 18:47    [15937761]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить