Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Web программирование > SQL, базы данных
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 16.07.2014, 21:00   #1
Pamparam
Форумчанин
 
Регистрация: 08.11.2009
Сообщений: 225
По умолчанию group by с количеством уникальных строк

Есть, например, коробки с фруктами. Надо найти такие коробки, где будут только указанные фрукты, например есть фрукты яблоко, апельсин, мандарин и нужно найти именно такую коробку:
korobki
id name co(кол-во фруктов в коробке)
1 pervaya 3
2 vtoraya 2

frukti_v_korobkah
id korobka_id frukt_id
1 1 3
2 1 4
3 1 4
4 2 1
5 2 3

Нужно выбрать коробку с 3,4,4, т.е. первую
Я юзаю group по korobka_id и делаю в
Код:
SELECT *
  FROM (
SELECT * ,
SUM(CASE WHEN frukt_id=3 THEN 1 ELSE 0 END) AS Count1
 ,SUM(CASE WHEN frukt_id=4 THEN 1 ELSE 0 END) AS Count2
 ,SUM(CASE WHEN frukt_id=4 THEN 1 ELSE 0 END) AS Count3
      FROM korobki
      WHERE  frukti_v_korobkah.korobka_id=korobki.id and IN(3,4,4)
      GROUP BY tradeid  HAVING korobki.co>=count1+count2+count3 and count1>0 and count2>0 and count3>0)
	   U,korobki,frukti_v_korobkah where u.id=frukti_v_korobkah.korobka_id and frukti_v_korobkah.korobka_id=korobki.id
т.е. делается груп по korobka_id и по 3 подзапроса, в которых делается запрос для каждого фрукта, чтобы потом сложить их и сравнить с korobki.co
Это ООООчень сильно долго работает, т.к. для каждой коробки делается 3 подзапроса. Помогите сделать это каким-то count(distinct ...) или т.п.
Нужно точно знать, что из поиска будет найдено именно коробку, в которой будет 3 строки, значения которых могут повторяться. Если кто знает как сильно упростить без уточнения повторений фруктов - подскажите хотя-бы так
Pamparam вне форума Ответить с цитированием
Старый 16.07.2014, 21:12   #2
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Код:
select
 korobka_id
from 
 korobki
where
 not korobka_id in
  (select korobka_id from korobki where not frukt_id in (3,4))
group by 1
Но это с потолка...
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 17.07.2014, 00:31   #3
Vapaamies
Ваш К. О.
Участник клуба
 
Аватар для Vapaamies
 
Регистрация: 26.12.2012
Сообщений: 1,774
По умолчанию

Классная задача. Сервак какой? Тут можно попробовать или full outer join, или minus, или intersect.
Vapaamies вне форума Ответить с цитированием
Старый 17.07.2014, 00:56   #4
Pamparam
Форумчанин
 
Регистрация: 08.11.2009
Сообщений: 225
По умолчанию

Цитата:
Сообщение от Vapaamies Посмотреть сообщение
Классная задача. Сервак какой? Тут можно попробовать или full outer join, или minus, или intersect.
mysql, основная задача чтобы грузило меньше, т.к. полей будет очень много
Pamparam вне форума Ответить с цитированием
Старый 17.07.2014, 10:16   #5
Vapaamies
Ваш К. О.
Участник клуба
 
Аватар для Vapaamies
 
Регистрация: 26.12.2012
Сообщений: 1,774
По умолчанию

Полей или записей? Поля ничего не стоят.
Vapaamies вне форума Ответить с цитированием
Старый 17.07.2014, 14:25   #6
Pamparam
Форумчанин
 
Регистрация: 08.11.2009
Сообщений: 225
По умолчанию

Цитата:
Сообщение от Vapaamies Посмотреть сообщение
Полей или записей? Поля ничего не стоят.
записей...
Pamparam вне форума Ответить с цитированием
Старый 17.07.2014, 18:24   #7
Vapaamies
Ваш К. О.
Участник клуба
 
Аватар для Vapaamies
 
Регистрация: 26.12.2012
Сообщений: 1,774
По умолчанию

Как-то так:
Код:
select
  k.id
from
  korobki k
left join
  frukti_v_korobkah apple on korobka_id = k.id and frukt_id = 3
left join
  frukti_v_korobkah orange on korobka_id = k.id and frukt_id = 4
left join
  frukti_v_korobkah mandarin on korobka_id = k.id and frukt_id = 5
group by
  k.id
having
  count(apple.frukt_id) > 0 and
  count(orange.frukt_id) > 0 and
  count(mandarin.frukt_id) > 0;
Vapaamies вне форума Ответить с цитированием
Старый 17.07.2014, 18:56   #8
Pamparam
Форумчанин
 
Регистрация: 08.11.2009
Сообщений: 225
По умолчанию

Цитата:
Сообщение от Vapaamies Посмотреть сообщение
Как-то так:
Код:
select
  k.id
from
  korobki k
left join
  frukti_v_korobkah apple on korobka_id = k.id and frukt_id = 3
left join
  frukti_v_korobkah orange on korobka_id = k.id and frukt_id = 4
left join
  frukti_v_korobkah mandarin on korobka_id = k.id and frukt_id = 5
group by
  k.id
having
  count(apple.frukt_id) > 0 and
  count(orange.frukt_id) > 0 and
  count(mandarin.frukt_id) > 0;
пример отличается от моего варианта только джоинами вместо кейса. По логике, кейс должен делать значительно меньше нагрузки, чем джоин
Pamparam вне форума Ответить с цитированием
Старый 17.07.2014, 19:00   #9
Vapaamies
Ваш К. О.
Участник клуба
 
Аватар для Vapaamies
 
Регистрация: 26.12.2012
Сообщений: 1,774
По умолчанию

Цитата:
Сообщение от Pamparam Посмотреть сообщение
пример отличается от моего варианта только джоинами вместо кейса. По логике, кейс должен делать значительно меньше нагрузки, чем джоин
На самом деле зависит от того, где и как используется case. Мой вариант подразумевает наличие индекса frukti_v_korobkah(korobka_id, frukt_id).

Над другими вариантами подумаю.
Vapaamies вне форума Ответить с цитированием
Старый 17.07.2014, 19:23   #10
Vapaamies
Ваш К. О.
Участник клуба
 
Аватар для Vapaamies
 
Регистрация: 26.12.2012
Сообщений: 1,774
По умолчанию

Вспомнил, что у меня локально стоит MySQL и чуток поэкспериментировал. Получилось так:
Код:
select korobka_id from (
  select
    korobka_id,
    case when frukt_id = 3 then 1 end apple,
    case when frukt_id = 4 then 1 end orange,
    case when frukt_id = 5 then 1 end mandarin
  from
    frukti_v_korobkah
  where
    frukt_id in (3, 4, 5)
) tt
group by
  korobka_id
having
  count(apple) > 0 and
  count(orange) > 0 and
  count(mandarin) > 0;
Этот запрос подразумевает наличие индекса frukti_v_korobkah(frukt_id), а необходимость в frukti_v_korobkah(korobka_id) нужно смотреть по плану.

Проверял inline-таблицей с четырьмя коробками:
Код:
select korobka_id from (
  select
    korobka_id,
    case when frukt_id = 3 then 1 end apple,
    case when frukt_id = 4 then 1 end orange,
    case when frukt_id = 5 then 1 end mandarin
  from (
    select 1 korobka_id, 3 frukt_id
    union all
    select 1, 4
    union all
    select 1, 5
    union all
    select 2, 1
    union all
    select 2, 3
    union all
    select 3, 1
    union all
    select 3, 2
    union all
    select 3, 4
    union all
    select 3, 5
    union all
    select 4, 1
    union all
    select 4, 2
    union all
    select 4, 3
    union all
    select 4, 4
    union all
    select 4, 5
  ) frukti_v_korobkah
  where
    frukt_id in (3, 4, 5)
) tt
group by
  korobka_id
having
  count(apple) > 0 and
  count(orange) > 0 and
  count(mandarin) > 0;
Vapaamies вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
масив с неопределенным количеством строк kalpak44 Общие вопросы C/C++ 5 27.12.2012 16:21
Как просуммировать столбец с неизвестным количеством строк? vpm Microsoft Office Excel 2 06.11.2012 10:30
Сводная таблица с большим количеством строк s8259 Microsoft Office Excel 1 03.04.2011 00:28
Создание новой формы с нужным количеством строк. konistra Microsoft Office Excel 13 01.06.2010 23:28
простая сортировка с заранее неизвестным количеством строк ShamanK Microsoft Office Excel 4 05.05.2010 16:50