SQL Server-在查询结果中多次列出单行

时间:2018-09-20 22:18:52

标签: sql sql-server common-table-expression

我在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 :(得分:2)

您可以尝试使用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

答案 1 :(得分:1)

另一种选择是临时计数/数字表

示例

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

或简单的加入

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

答案 2 :(得分:0)

使用存储过程 创建一个临时表变量 在while循环中将insert写入临时表 而计数器

最后从表格中选择。

答案 3 :(得分:0)

已编辑:

(谢谢@MatBailie!)

num列上使用递归CTE生成所需的重复次数,并进行左联接:

给出表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