Страница 1 из 1
Помогите с запросом...
Добавлено: 25 мар 2008, 23:11
avenger
Добрый вечер!
Пусть имеется данные
Необходимо найти, было ли, если вести обход в порядке возрастания номера, пересечение по пользователю. Т.е. одновременно с первым пользователем работал ли второй. Например: для пользователя #1 min(num) < num=3 < max(num) => c первым пользователем одновременно работал 2-й. В это же время для пользователя #2 есть пересечение с пользователем #1, т.к. документ с номером 3-и лежит между документами с номерами 2 и 4, которые принадлежат 1-му пользователю.
Другой пример:
Здесь у пользователей #1, #2 и #3 нет пересечений между друг другом.
Помогите мне написать процедуру, которая бы по ID пользователя возвращала бы true/false в зависимости от того, есть пересечение или нет. Можно просто идею.
За ранее спасибо. С уважением, Иван.
Добавлено: 26 мар 2008, 08:25
Tonal
Т.е. тебе нужно выяснить, встречаются ли для заданного числа такие, которые встречаются в последовательности и до его появления и после?
Вот код на python-е:
Код: Выделить всё
def cross_test(test_id, seq):
before = set() #Множество встреченных перед предыдущим появлением test_id чисел
before2 = set() #Множество встреченных чисел
for it in seq:
if it != test_id:
if it in before: #it появлялся перед предыдущим появлением test_id
return True
before2.add(it)
else:
before.update(before2)
return False
Ну а на PSQL думаю сам переведёшь, меня - ломает

Добавлено: 26 мар 2008, 08:37
avenger
Tonal писал(а):Т.е. тебе нужно выяснить
Мне надо вычислить - пересекаются диапазоны или нет. Т.е. для первого примера имеем 2-а диапазона:
Видно, что диапазон для 1-го пользователя пересекается с диапазоном 2-го и наоборот.
Для 2-го примера
Пересечений диапазонов нет.
Вот, навоял запрос. Помогите упростить:
Код: Выделить всё
SELECT T2.USERFK
FROM TABLE1 T1
JOIN TABLE1 T2 ON T2.USERFK <> T1.USERFK
WHERE T1.USERFK = :ID
GROUP BY 1, T2.NUM
HAVING (T2.NUM BETWEEN MIN(T1.NUM) AND MAX(T1.NUM))
UNION ALL
SELECT T2.USERFK
FROM TABLE1 T1
JOIN TABLE1 T2 ON T2.USERFK <> T1.USERFK
WHERE T1.USERFK = :ID
GROUP BY 1, T1.NUM
HAVING (T1.NUM BETWEEN MIN(T2.NUM) AND MAX(T2.NUM))
Добавлено: 26 мар 2008, 11:24
Кузнецов Евгений
Доброго времени суток!
avenger писал(а):Мне надо вычислить - пересекаются диапазоны или нет.
Условие пересечения будет таким:
(T1.Min_Num <= T2.Max_num ) and (T2.Min_num <= T1.Max_num)
Добавлено: 26 мар 2008, 11:42
avenger
Кузнецов Евгений писал(а):(T1.Min_Num <= T2.Max_num ) and (T2.Min_num <= T1.Max_num)
То, что нужно.
Код: Выделить всё
select t2.userfk
from table1 t1
join table1 t2 on t2.userfk <> t1.userfk
where t1.userfk = :id
group by 1
having ( (min(t1.num) <= max(t2.num)) and (min(t2.num) <= max(t1.num)) )
А другой способ есть решить эту задачу?
Добавлено: 26 мар 2008, 11:49
Tonal
Если для 2х указанных пользователей, нужно узнать пересекаются их "диапазоны" или нет - смотри ответ
Кузнецов Евгений.
Если нужно для одного узнать пересекался ли он с кем-нибудь, то алгоритм я привёл.

А если переводить на SQL - то надо выбрать множество всех пользователей в выборке, и для каждого из них проверить пересекается ли он с заданным.
Код вроде довольно простой, если использовать derived tables и подзапросы.
Хотя тут и having-ом вместо derived tables обойтись можно.

Добавлено: 26 мар 2008, 12:05
avenger
Tonal писал(а):Если нужно для одного узнать пересекался ли он с кем-нибудь, то алгоритм я привёл.

Запрос, приведенный мной постом выше, с учетом поправки Кузнецова Евгения, возвращает для заданного пользователя, с кем он пересекается. А не для двух заданных пользователей проверяет условие.
Добавлено: 26 мар 2008, 12:47
Tonal
Вот мой способ:
Код: Выделить всё
Макросы:
#GET_MIN(USER) -> (select MIN(NUM) from TBL where USER_FK = USER)
#GET_MAX(USER) -> (select MAX(NUM) from TBL where USER_FK = USER)
Запрос:
select exists(
select T1.USER_FK from TBL T1
where T1.USER_FK != :USER
group by T1.USER_FK
having
#GET_MIN(T1.USER_FK) < #GET_MAX(:USER) and #GET_MAX(T1.USER_FK) > #GET_MIN(:USER)
) from rdb$database
Здесь нужно в запросе заменить соответсвующие макросы на их определение.
Вроде должно быть побыстрее твоего?

Добавлено: 26 мар 2008, 12:48
Tonal
Да, если нужно получить всех с кем пересекается - то откусываешь внешний exists.

Добавлено: 26 мар 2008, 13:56
WildSery
Tonal писал(а): - то откусываешь внешний exists.

... и добавляешь distinct. Или группировку. Хотя что это я? Ведь получится опять having
