Можно ли группировать по комбинации строк? - PullRequest
3 голосов
/ 14 июля 2010

У меня есть результат, который дает мне диапазон значений для запроса из моей базы данных:

Start        End
-----        ---
    1          3
    5          6
  137        139      

Из них мне нужно запросить в базе данных записи в этом диапазоне, которые могут возвращать что-то вроде:

Id    Name
----- ------
    1 foo
    2 bar
    3 baz

Id    Name
----- ------
    5 foo
    6 baz

Id    Name
----- ------
  137 foo
  138 bar
  139 baz

Я хочу сгруппировать их результаты, сохранив любой из диапазонов идентификаторов, поскольку они соотносятся с одним и тем же. Например, 1-3 - это то же самое, что и 137-139, поэтому он будет иметь счет 2, но, конечно, «диапазон» может быть любым из 2:

RangeStart   RangeEnd   Count
----------   --------   -----
       137        139       2
         5          6       1

Также обратите внимание, что порядок должен изменить группировку, поэтому foo / bar / baz - это не то же самое, что foo / baz / bar.

Как это можно сделать?

РЕДАКТИРОВАТЬ: у меня есть начальный результат (начало, конец), и я забочусь только о конечном результате (RangeStart, RangeEnd, Count). На самом деле мне не нужны промежуточные результаты, я просто использую их в качестве объяснения.

1 Ответ

3 голосов
/ 15 июля 2010

Вот два запроса:

  • Первый объединяет строки в группы на основе диапазонов, а затем показывает первый диапазон для каждой группы строк.Он также содержит общее количество раз, когда строка появилась.
  • Вторая показывает объединенные строки и их итоговые значения.

Настройка:

DECLARE @Tags TABLE ( 
  TagID INT, 
  Tag   VARCHAR(3) 
)  

INSERT @Tags  
SELECT 1, 'Foo' UNION ALL 
SELECT 2, 'Bar' UNION ALL 
SELECT 3, 'Baz' UNION ALL 
SELECT 4, 'Foo' UNION ALL 
SELECT 5, 'Bar' UNION ALL
SELECT 6, 'Baz'

DECLARE @Ranges TABLE ( 
  StartRange INT,  
  EndRange   INT 
) 

INSERT @Ranges 
SELECT 1,3 UNION ALL 
SELECT 2,3 UNION ALL  
SELECT 3,4 UNION ALL 
SELECT 4,6

Запрос на отображение первых диапазонов и результатов:

/* Get the first start and end ranges with a match and */
/* the total number of occurences of that match        */
SELECT
  StartRange,
  EndRange,
  Total
FROM (
  SELECT
    StartRange,
    EndRange,  
    Csv,
    ROW_NUMBER() OVER (PARTITION BY Csv ORDER BY StartRange ASC)  AS RowNum,
    ROW_NUMBER() OVER (PARTITION BY Csv ORDER BY StartRange DESC) AS Total
  FROM ( 
    /* For each range and its associated Tag values, */ 
    /* Concatenate the tags together using FOR XML   */ 
    /* and the STUFF function                        */ 
    SELECT 
      StartRange, 
      EndRange, 
      ( 
      SELECT STUFF(   
      (SELECT ',' + Tag 
      FROM @Tags WHERE TagID BETWEEN r.StartRange AND r.EndRange 
      ORDER BY TagID 
      FOR XML PATH('')),1,1,'')  
      ) AS Csv 
    FROM @Ranges r
  ) t1 
) t2
WHERE RowNum = 1
ORDER BY StartRange, EndRange

/* Results */

StartRange  EndRange    Total
----------- ----------- -----
1           3           2
2           3           1
3           4           1

Запрос на отображение связанных строк и итогов:

/* Get the concatenated tags and their respective totals */ 
SELECT
  Csv,
  COUNT(*) AS Total
FROM ( 
  /* For each range and its associated Tag values, */ 
  /* Concatenate the tags together using FOR XML   */ 
  /* and the STUFF function                        */ 
  SELECT 
    StartRange, 
    EndRange, 
    ( 
    SELECT STUFF(   
    (SELECT ',' + Tag 
    FROM @Tags WHERE TagID BETWEEN r.StartRange AND r.EndRange 
    ORDER BY TagID 
    FOR XML PATH('')),1,1,'')  
    ) AS Csv 
  FROM @Ranges r 
) t1 
GROUP BY Csv
ORDER BY Csv

/* Results */

Csv          Total
------------ -----------
Bar,Baz      1
Baz,Foo      1
Foo,Bar,Baz  2

Метод конкатенации строк любезно предоставлен Иеремия Песка

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...