2014-07-26 7 views
3

У меня возникла такая проблема. Существует таблица A, я хочу ее заполнить с помощью команды `group by x by diff (которая является абс (x-y)) с поправкойАгрегат с groupby, но с отличным условием на агрегированном столбце

x и y всегда идет постепенно. И х с меньшим значением будет иметь приоритет, когда два разных х можно в паре с таким же у

x  y  diff 
    1  2  1 
    1  4  3 
    1  6  5 
    3  2  1 
    3  4  1 
    3  6  3 
    4.5 2  3.5 
    4.5 4  0.5 
    4.5 6  1.5 

агрегатной функции Я хочу это:

взять у в каждой группе, которая имеет наименьшее значение с х (наименьшее значение разности).

НО, что у которого взят не может быть использован повторно. (Например, у = 2 будет принято в (х = 1) группы, так что не может быть повторно использован в (х = 3) группы)

Ожидаемое результат:

x  y  diff 
    1  2  1 
    3  4  1 
    4.5 4  0.5 

кажется очень сложным в простом SQL. Я использую PostgreSQL. Реальные данные будут гораздо сложнее и дольше, чем эта идея стреляющий например

+1

Ваши требования не определяют уникальный результат. Если один и тот же 'y' имеет минимальную разницу между двумя разными значениями' x', как вы должны определить, с каким 'x' следует с ним связать? Помните, что таблица базы данных может иметь физический порядок для строк, но она не имеет логического порядка. –

+0

Итак 'diff' равно' abs (x-y) '? Вы должны написать это явно, если это так. –

+1

Что делать, если все значения y с наименьшим значением diff уже использовались, например.для x = 3, y = 2 и y = 4 с diff 1 уже использовались, если это вернет y = 6? – dnoeth

ответ

0

Try как этот

t1 как имя таблицы

d, как дифф

with cte as (
    select x, y,d from t1 where d=(select min(d) from t1) order by x) 
    select t1.x, min(t1.y), min(t1.d) from t1 inner join cte on 
    t1.x=cte.x and not t1.y in (select y from cte where cte.x<t1.x) 
    group by t1.x 
+0

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

1

Если правильно понял ваш вопрос

test=# select * from A; 
x | y | diff 
---+---+------ 
1 | 2 | 1 
1 | 4 | 3 
1 | 6 | 5 
3 | 2 | 1 
3 | 4 | 1 
3 | 6 | 3 
5 | 2 | 3 
5 | 4 | 1 
5 | 6 | 1 
(9 rows) 

test=# SELECT MIN(x) AS x, y FROM A WHERE diff = 1 GROUP BY y ORDER BY x; 
x | y 
---+--- 
1 | 2 
3 | 4 
5 | 6 
(3 rows) 

SELECT MIN(x) AS x, y, MIN(diff) FROM A WHERE diff = 1 GROUP BY y ORDER BY x; 
x | y | min 
---+---+----- 
1 | 2 | 1 
3 | 4 | 1 
5 | 6 | 1 
(3 rows) 

добавлено MIN(diff), если не требуется, можно удалить.

+0

Благодарю вас за ответ, но выбранный выбор не всегда будет 1, может быть что-то минимальное в группе в соответствии с x –

+0

Надеюсь, это то, что вам нужно :) 'SELECT min (tb2.x), tb1.y, tb1.diff FROM (SELECT y, MIN (diff) AS diff FROM A GROUP BY y) AS tb1 LEFT JOIN (SELECT * FROM A) AS tb2 ON (tb1.y = tb2. y AND tb1.diff = tb2.diff) GROUP BY tb1.y, tb1.diff' – Rhim

0

Это скорее комментарий.

Эта проблема представляет собой проблему графа, заключающуюся в нахождении кратчайших пар множеств между двумя дискретными множествами (в данном случае х и у). Технически это максимальное совпадение взвешенного двудольного графа (см. [Здесь] [1]). Я не думаю, что эта проблема NP-полная. Но это все еще может затруднить решение, особенно в SQL.

Независимо от того, сложно или нет в теоретическом смысле (NP-complete считается «теоретически трудным»), в SQL это сложно сделать. Одна из проблем заключается в том, что жадные алгоритмы не работают. То же самое значение «y» может быть самым близким к всем значениям X. Какой из них выбрать? Ну, алгоритм должен смотреть дальше.

Единственный способ, с помощью которого я могу сделать это в SQL, - это исчерпывающий подход. То есть, сгенерируйте все возможные комбинации, а затем проверьте, что соответствует вашим условиям. Поиск всех возможных комбинаций требует генерации N-факториальных комбинаций X (или Y). Это, в свою очередь, требует большого количества вычислений. Моя первая мысль заключалась в использовании рекурсивных CTE для этого. Однако это будет работать только на небольших проблемах.

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