Нахождение наиболее конкретного префикса с SQL - PullRequest
1 голос
/ 09 октября 2009

У меня немного проблемы с SQL. Вот мои таблицы:

areas(id, name, sla_id)
areas_groups(id, group_id, areaprefix)

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

Поле areaprefix является интересным. Он содержит только первые несколько цифр sla_id и является уникальным. Каждая область может существовать только в одной группе, поэтому эта область принадлежит группе с наиболее специфичным префиксом . Пример:

Group 12's area prefixes: 105, 110, 115, 805
Group 13's area prefixes: 1, 8

Area sla_id = 10533071 matches both group 12 (105*) and group 13 (1*)
              "105" is longer, so this area is in group 12
Area sla_id = 81031983 matches only group 13 (8*)

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

Я могу найти, в какой группе находится область, вот так:

-- eg: area with sla_id 105055200
SELECT * FROM (
    SELECT group_id
    FROM areas_groups
    WHERE SUBSTR('105055200', 0, LENGTH(area_prefix)) = area_prefix
    ORDER BY LENGTH(area_prefix) DESC
)
WHERE rownum = 1;

(я уже говорил, что это Oracle?)

Другой путь - хитрый: учитывая идентификатор группы, я хочу найти все области, которые принадлежат этой группе. То есть для данной группы 13 мне нужны все области, которые начинаются с 1 или 8, но не с 105, 110, 115 или 805 (в этом примере).

Самое близкое, что я пришел, это:

SELECT a.id, a.sla_id, MAX(LENGTH(ag.area_prefix)), ag.group_id
FROM areas a INNER JOIN areas_groups ag
    ON (SUBSTR(a.sla_id, 0, LENGTH(ag.area_prefix)) = ag.area_prefix)
WHERE a.sla_id IS NOT NULL
GROUP BY a.id, a.sla_id, ag.group_id

Это возвращает данные как это:

 id     sla_id    leng   group_id
583    105308400    3    12
583    105308400    1    13
584    105556700    3    12
584    105556700    1    13

Так что, если бы я мог только взять group_id, который имеет самую длинную длину для каждого идентификатора ... У меня такое чувство, что я действительно близок, но просто скучаю по крошечной мелочи ... Может кто-нибудь помочь вытащить меня из моего страдания?

Ответы [ 2 ]

2 голосов
/ 09 октября 2009
select id
,      sla_id
,      leng
,      group_id
,      (row_number() over (partition by id order by leng desc)) rn 
from 
(
SELECT a.id, a.sla_id, MAX(LENGTH(ag.area_prefix)) leng, ag.group_id
FROM areas a INNER JOIN areas_groups ag
    ON (SUBSTR(a.sla_id, 0, LENGTH(ag.area_prefix)) = ag.area_prefix)
WHERE a.sla_id IS NOT NULL
GROUP BY a.id, a.sla_id, ag.group_id
)
where rn = 1
1 голос
/ 09 октября 2009

Это не проверено в Oracle, но я считаю, что Oracle поддерживает COALESCE как строковую функцию начиная с версии 9, так что это должно быть в порядке, если вы не работаете над старой версией Oracle.

Я предположил, что есть также группа area_prefix записей с двумя символами.

select  a.id
        ,a.sla_id
        ,coalesce(ag3.area_prefix,ag2.area_prefix,ag1.area_prefix) area_prefix
        ,coalesce(ag3.group_id,ag2.group_id,ag1.group_id) group_id
from areas a
left join areas_groups ag3
on        substr(a.sla_id,1,3) = ag3.area_prefix
left join areas_groups ag2
on        substr(a.sla_id,1,2) = ag2.area_prefix
left join areas_groups ag1
on        substr(a.sla_id,1,1) = ag1.area_prefix
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...