我有两列
我想输出查询
我尝试在 SQL 中使用循环,但我未能输出查询
我的问题是:如何通过 [Total] 列中的数字重复 [Name] 列中的值?
This is usually handled with a recursive subquery. I derived a row order in case of duplicate names, however, that is best served using a unique key.
MS SQL Server 2017 Schema Setup:
CREATE TABLE Names(name NVARCHAR(50), total INT)
INSERT Names VALUES('ahmed',3),('mahmoud',2),('ahmed',5)
Query 1:
;WITH Normalized AS
(
SELECT *, RowNumber = ROW_NUMBER() OVER (ORDER BY (SELECT 0)) FROM Names
)
,ReplicateAmount AS
(
SELECT name, running_total=total, total, RowNumber
FROM Normalized
UNION ALL
SELECT R.name, running_total=(R.running_total - 1), R.total , R.RowNumber
FROM ReplicateAmount R INNER JOIN Normalized N ON R.RowNumber = N.RowNumber
WHERE R.running_total > 1
)
SELECT
name,instance=RowNumber,total=1,OriginalTotal=total,running_total
FROM
ReplicateAmount
ORDER BY
RowNumber,name,total,running_total
OPTION (MAXRECURSION 0)
| name | instance | total | OriginalTotal | running_total |
|---------|----------|-------|---------------|---------------|
| ahmed | 1 | 1 | 3 | 1 |
| ahmed | 1 | 1 | 3 | 2 |
| ahmed | 1 | 1 | 3 | 3 |
| mahmoud | 2 | 1 | 2 | 1 |
| mahmoud | 2 | 1 | 2 | 2 |
| ahmed | 3 | 1 | 5 | 1 |
| ahmed | 3 | 1 | 5 | 2 |
| ahmed | 3 | 1 | 5 | 3 |
| ahmed | 3 | 1 | 5 | 4 |
| ahmed | 3 | 1 | 5 | 5 |
您可以比接受的答案简单得多。
我建议创建一个带有连续正整数的数字表...
CREATE TABLE dbo.Numbers(Number INT PRIMARY KEY);
INSERT INTO dbo.Numbers
SELECT TOP 10000 ROW_NUMBER() OVER (ORDER BY @@SPID)
FROM sys.all_objects o1,
sys.all_objects o2
然后加入number <= total
(如下)
SELECT name, 1 AS total
FROM Names nam
JOIN dbo.Numbers num ON num.Number <= nam.total;
如果您在 2017 年以上,另一种“有趣”的方法如下(SQL Fiddle)
SELECT name, 1 AS total
FROM Names
CROSS APPLY STRING_SPLIT(SPACE(total - 1), ' ')
对于您的封闭式问题;
CREATE TABLE #Test1(
[ID] [int] NULL,
[Cnt] [varchar](50) NULL
) ON [PRIMARY]
GO
CREATE TABLE #Test2(
[ID] [int] NULL,
[col1] [varchar](50) NULL,
[col2] [varchar](50) NULL,
[col3] [varchar](50) NULL
) ON [PRIMARY]
GO
CREATE TABLE #Test3(
[ID1] [int] NULL,
Cnt int,
Id2 int,
[col1] [varchar](50) NULL,
[col2] [varchar](50) NULL,
[col3] [varchar](50) NULL
) ON [PRIMARY]
GO
INSERT INTO #TEST1 (ID, Cnt) VALUES (1, 2)
INSERT INTO #TEST1 (ID, Cnt) VALUES (2, 3)
INSERT INTO #TEST1 (ID, Cnt) VALUES (3, 1)
INSERT INTO #TEST1 (ID, Cnt) VALUES (4, 2)
INSERT INTO #TEST1 (ID, Cnt) VALUES (5, 1)
INSERT INTO #TEST1 (ID, Cnt) VALUES (6, 4)
INSERT INTO #TEST2 (ID, Col1, Col2, Col3) VALUES (1, 'a1', 'b1', 'c1')
INSERT INTO #TEST2 (ID, Col1, Col2, Col3) VALUES (2, 'a2', 'b2', 'c2')
INSERT INTO #TEST2 (ID, Col1, Col2, Col3) VALUES (3, 'a3', 'b3', 'c3')
INSERT INTO #TEST2 (ID, Col1, Col2, Col3) VALUES (4, 'a4', 'b4', 'c4')
INSERT INTO #TEST2 (ID, Col1, Col2, Col3) VALUES (5, 'a5', 'b5', 'c5')
INSERT INTO #TEST2 (ID, Col1, Col2, Col3) VALUES (6, 'a6', 'b6', 'c6')
declare @a int = 1, @b int, @c int = 0;
while @a <= (select MAX(Id) from #Test1)
begin
set @b = (select Cnt from #Test1 where ID = @a);
set @c = 0;
while @c < @b begin
insert into #Test3 (ID1, Cnt, Id2, col1, col2, col3) select @a, @b, @a, col1, col2, col3 from #Test2 where ID = @a;
set @c += 1;
end
SET @a += 1;
end
select * from #Test3 order by 1, 2;