SQL Server - перечислять одну строку несколько раз в результате запроса - PullRequest
0 голосов
/ 21 сентября 2018

У меня есть набор данных в базе данных SQL Server, и я хотел бы составить список, выполнить запрос для вывода списка записей из таблицы, несколько раз в соответствии с соответствующим целочисленным значением в столбце этой таблицы.

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

Структура таблицы записей похожа на следующую:

+-----+-------+------+------+
| id  | name  | type | num  |
+-----+-------+------+------+
| 1   | bob   | red  | 1    |
+-----+-------+------+------+
| 2   | sam   | blue | 3    |
+-----+-------+------+------+
| 3   | viv   | green| 2    |
+-----+-------+------+------+

Я быхотелось бы отобразить это в результате запроса следующим образом ...

+-----+-------+------+
| id  | name  | type |
+-----+-------+------+
| 1   | bob   | red  |
+-----+-------+------+
| 2   | sam   | blue |
+-----+-------+------+
| 2   | sam   | blue |
+-----+-------+------+
| 2   | sam   | blue |
+-----+-------+------+
| 3   | viv   | green|
+-----+-------+------+
| 3   | viv   | green|
+-----+-------+------+

... где каждая запись появляется несколько раз в соответствии с номером, указанным в исходной строке.(Боб * 1, Сэм * 3, Вив * 2)

Возможно ли это с помощью перекрестного соединения или любого другого метода?


Примечание: Это не обязательно должно быть очень эффективно.

Ответы [ 4 ]

0 голосов
/ 21 сентября 2018

РЕДАКТИРОВАНИЕ:

(Спасибо, @MatBailie!)

Использование рекурсивного CTE для столбца num для генерации необходимого количества повторений и выполнение левого соединения:

Дана таблица so1 следующим образом:

   id   name   type    num
    1   bob    red      1
    2   sam    blue     3
    3   viv    green    2
    4   jon    grey     7 

Попробуйте:

WITH RECURSIVE exp_num AS
(
SELECT id, num FROM so1
UNION
SELECT id, num - 1 FROM exp_num WHERE num > 1
)

SELECT s1.* FROM so1 s1
LEFT JOIN
(
SELECT id FROM exp_num
) s2
ON s1.id = s2.id

Вывод:

id  name  type
1   bob   red 
2   sam   blue      
2   sam   blue      
2   sam   blue      
3   viv   green     
3   viv   green     
4   jon   grey      
4   jon   grey      
4   jon   grey      
4   jon   grey     
4   jon   grey      
4   jon   grey      
4   jon   grey      
0 голосов
/ 21 сентября 2018

Вы можете попробовать использовать recursive CTE

;with cte as (
    SELECT id,name,type,1 startnum,num    
    FROM T
    UNION ALL
    SELECT id,name,type , startnum+1,num    
    FROM cte
    WHERE startnum+1<=num
)

SELECT id,name,type
FROM cte
order by id

sqlfiddle

0 голосов
/ 21 сентября 2018

Другим вариантом является специальная таблица подсчета / чисел

Пример

Select A.ID
      ,A.[Name]
      ,A.[Type]
 From  YourTable A
 Cross Apply (Select Top (A.[num]) N=Row_Number() Over (Order By (Select NULL)) From master..spt_values n1) B

Или просто JOIN

Select A.ID
      ,A.[Name]
      ,A.[Type]
 From YourTable A
 Join (Select Top (100) N=Row_Number() Over (Order By (Select NULL)) From master..spt_values n1) B
   on B.N<=A.[Num]

Оба вернутся

ID  Name    Type
1   bob     red
2   sam     blue
2   sam     blue
2   sam     blue
3   viv     green
3   viv     green
0 голосов
/ 21 сентября 2018

Использование хранимой процедуры для создания временной переменной таблицы. Запись вставки во временную таблицу в цикле while, в то время как вставка счетчика

Окончательно выбирает из таблицы.

...