Как найти ближайших соседей в sql teradata? - PullRequest
0 голосов
/ 29 октября 2018

Я хочу найти 1 ближайшего соседа для каждого клиента из таблицы TG. Решение должно быть принято с использованием расстояния, рассчитанного на val.

Одним из возможных решений является перекрестная таблица соединений на себя, но «TG» имеет размер 100 КБ, а исходная таблица 50 млн. - для большой производительности. Итак, я пришел к идее, используя оконную функцию:

Я не могу заставить работать такой алгоритм. Так как я могу это сделать?

SELECT 
   cust_id2,
   MIN(CASE WHEN cust_id <> cust_id2 then cust_id end) -- to get for cust_id2 from TG another cust_id from all_custs table
   OVER (PARTITION BY cust_id2 
   ORDER BY SQRT(POWER(cur.val1 - pref.val1, 2) + POWER(cur.val2 - pref.val2, 2)) -- here I want to order by distance but I need current value and previous one. Nested windows function isn't allowed(
FROM 
(
   select all_custs.cust_id, val1, val2,  aa.cust_id2 from all_custs
   left join (sel cust_id as cust_id2 from TG) TG,  aa on aa.cust_id2 = all_custs.cust_id 
) AS dt
where cust_id2 is not null


`TG` - stores just ids - as numbers. Every cust from TG are also in `all_custs` 

Table all_custs 

cust_id (number) | val1(decimal) | val2(decimal)
_________________|_______________|_____________
123123131        | 123.1         | 2
234234241        | 75.15         | 5 
525165354        | 676.12        | 3

Для cust_id = 123123131 ближайшим из них будет cust 234234241. Может быть более одного столбца val

UPD1: для справки. Вот как это можно сделать с помощью перекрестного соединения, но не следует:

sel tg.cust_id as tg_cust_id, cg.cust_id as cg_cust_id
SQRT   (
            POWER((tg.val1 - cg.val1)/max_val1, 2) -- min = 0
          + POWER((tg.val2 - cg.val2)/max_val2, 2) -- min = 0 
       ) AS DIST
   from (
       sel arpau.cust_id, val1, val2
       from all_custs join TG aa on aa.cust_id2 = arpau.cust_id
       where arpau.branch_id = 95 
   ) tg
   join ( 
    sel arpau.cust_id, val1, Max(val1)  over(ROWS UNBOUNDED PRECEDING) max_val1
                     , val2, Max(val1)  over(ROWS UNBOUNDED PRECEDING) max_val2
            from all_custs left join TG aa on aa.cust_id2 = arpau.cust_id
       where aa.cust_id2 is null       
    ) cg  on  tg.cust_id <> cg.cust_id
QUALIFY ROW_NUMBER() OVER(PARTITION BY tg.cust_id ORDER BY DIST) = 1
...