Группировка по нечеткому критерию - PullRequest
0 голосов
/ 13 апреля 2011

Есть ли способ выполнить эту задачу в SQL:

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

 luggage_id | luggage_name | luggage_weight   
------------+--------------+----------------  
          1 | Tom          |              2  
          2 | Kat          |              3  
          3 | Lil          |              4  

выводит группы вещей, которые отличаютсявес меньше или точно D единиц.Таким образом, если D равно 1, мы должны получить

1. Tom, Kat
2. Kat, Lil

, а если D равно 2, мы должны получить

1. Tom, Kat, Lil

, а если D равно 0,5, мы получим

1. Tom
2. Kat
3. Lil

Я пытался использовать перекрестное соединение:

SELECT t1.luggage_name, t2.luggage_name
FROM Luggages t1, Luggages t2
WHERE ABS(t1.luggage_weight - t2.luggage_weight) <= 1

, что привело к


 luggage_name | luggage_name 
--------------+--------------
 Tom          | Tom
 Tom          | Kat
 Kat          | Tom
 Kat          | Kat
 Kat          | Lil
 Lil          | Kat
 Lil          | Lil

Возможно ли решить эту проблему с помощью SQL?

EDIT Хорошо, да, мы можем написать

SELECT t1.luggage_name, t2.luggage_name
FROM Luggages t1, Luggages t2
WHERE ABS(t1.luggage_weight - t2.luggage_weight) <= 1
      AND t1.luggage_id < t2.luggage_id

, тогда мы получим

 luggage_name | luggage_name 
--------------+--------------
 Tom          | Kat
 Kat          | Lil

Это означает, что Том в группе с Кэт, а Кэт в группе с Лил.

Но, скажем, у нас есть таблица с одинаковыми весами


 luggage_id | luggage_name | luggage_weight 
------------+--------------+----------------
          1 | Tom          |              1
          2 | Kat          |              1
          3 | Lil          |              1

Тогда мы получим


 luggage_name | luggage_name 
--------------+--------------
 Tom          | Kat
 Tom          | Lil
 Kat          | Lil

Это означает, что Том с Кэт и Лил, чтоправильно, но следующая группа, Кат с Лил уже в первой группе.Я думал об этой проблеме и не могу понять, как ее решить.Как вывести только разные группы?

Ответы [ 2 ]

3 голосов
/ 13 апреля 2011

Требуется условие, чтобы ограничить полное декартово треугольным соединением

SELECT t1.luggage_name, t2.luggage_name
FROM Luggages t1, Luggages t2
WHERE ABS(t1.luggage_weight - t2.luggage_weight) <= 1

AND
t1.luggageid < t2.luggageid

Удаляет ненужные пары

Редактировать

Тогда вы получите

 luggage_name | luggage_name 
--------------+--------------
 Tom          | Kat
 Kat          | Lil

Когда d=0.5, тогда у вас есть нет пар, потому что нет разницы меньше 0,5. Список синглетонов на самом деле неверен по сравнению с выводом d <= 1

Редактировать 2: Доказательство для тех, кого вы не понимаете ...

DECLARE @luggage TABLE (luggageid int IDENTITY(1,1), luggage_name varchar(30), luggage_weight float)
INSERT @luggage (luggage_name, luggage_weight) VALUES ('Tom', 2), ('Kat', 3), ('Lil', 4)

SELECT t1.luggage_name, t2.luggage_name
FROM @luggage t1, @luggage t2
WHERE ABS(t1.luggage_weight - t2.luggage_weight) <= 1
AND
t1.luggageid < t2.luggageid


SELECT t1.luggage_name, t2.luggage_name
FROM @luggage t1, @luggage t2
WHERE ABS(t1.luggage_weight - t2.luggage_weight) <= 2
AND
t1.luggageid < t2.luggageid


SELECT t1.luggage_name, t2.luggage_name
FROM @luggage t1, @luggage t2
WHERE ABS(t1.luggage_weight - t2.luggage_weight) <= 0.5
AND
t1.luggageid < t2.luggageid
1 голос
/ 13 апреля 2011
SELECT t1.luggage_name, MIN(t2.luggage_name) GroupsWith
FROM Luggages t1
JOIN Luggages t2 ON ABS(t1.luggage_weight - t2.luggage_weight) <= 1
AND ((t1.luggage_weight < t2.luggage_weight)
  OR (t1.luggage_weight = t2.luggage_weight AND t1.luggage_name < t2.luggage_name))
GROUP BY t1.luggage_name
ORDER BY t1.luggage_name

Это покажет цепочку сгруппированных пользователей без дубликатов, поэтому, если у вас есть

Tom-2, Kat-3, Lil-4, Bob-5

Они все D = 1 друг от друга.Если ваш запрос имеет D = 1, он покажет

Kat Lil
Lil Bob
Tom Kat

, который показывает всю группу Tom-> Kat-> Lil-> Bob.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...