2013-06-06 2 views
0

Моя проблема показывает только идентификаторы сгруппированных уникальных наборов данных. Простой пример будет служить лучше всего:Выбрать идентификатор по сгруппированному уникальному набору данных

| id | color | 
-------------- 
| 1 | red | 
-------------- 
| 1 | green | 
-------------- 
| 1 | blue | 
-------------- 
| 2 | red | 
-------------- 
| 2 | green | 
-------------- 
| 2 | blue | 
-------------- 
| 3 | red | 
-------------- 
| 3 | blue | 
-------------- 
| 3 | yellow| 
-------------- 
| 3 | purple| 
-------------- 

Id 1 и ID 2 имеют те же подмножества данных (красный, зеленый, синий), так что таблица результат должен содержать только 1 или 2:

| id | 
------ 
| 1 | 
------ 
| 3 | 
------ 

Я предполагаю, что эта относительно основная проблема задавалась несколько раз, но я не мог прибить конкретные ключевые слова, которые могли бы привести к результатам.

ответ

1

Хотя SQLite имеет group_concat(), здесь это не поможет, потому что порядок конкатенированных элементов произволен. Это самый простой способ сделать это.

Вместо этого мы должны думать об этом реляционно. Идея заключается в том, чтобы сделать следующее:

  1. Подсчитайте количество цветов, что два Идентификаторы имеют в общей
  2. Подсчитайте количество цветов на каждом ид
  3. Выберите пары идентификаторов, где эти три значения равны
  4. Определите каждую пару по минимальному id в паре

Тогда различные значения минимума - это список, который вы хотите.

Следующий запрос принимает этот подход:

select distinct MIN(id2) 
from (select t1.id as id1, t2.id as id2, count(*) as cnt 
     from t t1 join 
      t t2 
      on t1.color = t2.color 
     group by t1.id, t2.id 
    ) t1t2 join 
    (select t.id, COUNT(*) as cnt 
     from t 
     group by t.id 
    ) t1sum 
    on t1t2.id1 = t1sum.id and t1sum.cnt = t1t2.cnt join 
    (select t.id, COUNT(*) as cnt 
     from t 
     group by t.id 
    ) t2sum 
    on t1t2.id2 = t2sum.id and t2sum.cnt = t1t2.cnt 
group by t1t2.id1, t1t2.cnt, t1sum.cnt, t2sum.cnt 

Я на самом деле испытал это в SQL Server, поместив эту with положение перед:

with t as (
     select 1 as id, 'r' as color union all 
     select 1, 'g' union all 
     select 1, 'b' union all 
     select 2 as id, 'r' as color union all 
     select 2, 'g' union all 
     select 2, 'b' union all 
     select 3, 'r' union all 
     select 4, 'y' union all 
     select 4, 'p' union all 
     select 5 as id, 'r' as color union all 
     select 5, 'g' union all 
     select 5, 'b' union all 
     select 5, 'p' 
    ) 
+1

[SQL Fiddle] (http://www.sqlfiddle.com/#!5/e00f7/1) –

+0

Кажется, что это работает, хотя я все еще пытаюсь обвести вокруг себя :-) Знаете ли вы, как Perfomance касается больших объединенных таблиц? @CL: аккуратный сайт – kadir

+0

@GnrlKnowledge. , , Вам нужно будет проверить производительность самостоятельно в своих системах. Большое объединение - первое, и ему может помочь указатель на 'color'. –

1

SQL ориентирован набор-, так что давайте попробуем это :

Уникальные идентификаторы - это идентификаторы, для которых нет другого идентификатора, который имеет одинаковый набор цветов.

Чтобы определить, являются ли два идентификаторы имеют одинаковые наборы цветов, мы subtract их друг от друга (это то, что EXCEPT делает) и проверить, является ли результат пуст в обоих направлениях:

SELECT id 
FROM (SELECT DISTINCT id FROM t) AS t1 
WHERE NOT EXISTS (SELECT id FROM (SELECT DISTINCT id FROM t) AS t2 
        WHERE t2.id < t1.id 
        AND NOT EXISTS (SELECT color FROM t WHERE id = t1.id 
            EXCEPT 
            SELECT color FROM t WHERE id = t2.id) 
        AND NOT EXISTS (SELECT color FROM t WHERE id = t2.id 
            EXCEPT 
            SELECT color FROM t WHERE id = t1.id)); 

SQL Fiddle

+0

Мне нравится ваше решение немного больше, очень чистый и классный подход! – kadir

Смежные вопросы