Группировать связанные записи в запросе SQL с опережением / отставанием - PullRequest
0 голосов
/ 12 декабря 2018

Учитывая

input_fid   near_fid
465         466
465         467
465         468
466         467
466         468
467         468
469         470
470         471

Как бы мне было сгенерировать вывод:

input_fid   near_fids
465         466,467,468 
469         470,471

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

Результирующий набор является динамическим и выводится инструментом, который определяет отношения между записями.Таким образом, логика такова, что 465 близок к 466 и 467 и 468, а 466 близок к 467 к 468 и так далее.Но ни одна предыдущая запись не близка к 469, следовательно, новая строка.

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

Я играл с различными итерациями опережения и отставания, а также использовал оператор WITH с разной степенью успеха, но ничего, что могло бы заставить меня чувствовать, что я близок.Одна итерация, которая была близка, за исключением дубликатов, была:

WITH n(input_fid, near_fid, level) AS ( SELECT input_fid, near_fid, 0 as level from results where input_fid < near_fid and input_fid between 465 and 471 and near_fid between 465 and 471 UNION ALL SELECT m.input_fid, m.near_fid, level + 1 from results where m.input_fid > m.near_fid and m.input_fid between 465 and 471 and m.near_fid between 465 and 471 and m.near_fid = n.input_fid ) SELECT input_fid, level, near_fid = STUFF((SELECT ', ' + CONVERT (VARCHAR (MAX), near_fid ) FROM n b WHERE n.input_fid = b.input_fid AND n.level = b.level order by near_fid FOR XML PATH('')), 1, 2, '') FROM n where level = 0 GROUP BY input_fid, level

1 Ответ

0 голосов
/ 12 декабря 2018

Это похоже на то, что вы ищете.Не уверен, что мне нравится тот факт, что я сканирую таблицу 3 раза, хотя:

WITH VTE AS(
    SELECT *
    FROM (VALUES (465,466),
                 (465,467),
                 (465,468),
                 (466,467),
                 (466,468),
                 (467,468),
                 (469,470)) V(input_fid, near_fid))
SELECT input_fid,
       STUFF((SELECT ',' + CONVERT(varchar(3),s.near_fid)
              FROM VTE s
              WHERE s.input_fid = V.input_fid
              ORDER BY s.near_fid
              FOR XML PATH('')),1,1,'') AS near_fids
FROM VTE V
WHERE NOT EXISTS(SELECT 1
                 FROM VTE e
                 WHERE V.input_fid = e.near_fid)
GROUP BY V.input_fid;

Обратите внимание, что outfor для near_fids для input_fid 469 только 470, как ваш образецданные не содержат строк или столбцов со значением 471;поэтому я понятия не имею, откуда он взялся.

...