可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Let say I have table #Foo:
Id Color -- ---- 1 Red 2 Green 3 Blue 4 NULL
And table #Bar:
Value ----- 1 2.5
I would like to create table Result using simple statement to get:
Id Color Value -- ---- ----- 1 Red 1 2 Green 2.5 3 Blue NULL 4 NULL NULL
What I have invented so far is:
WITH cte1 AS ( SELECT [Id], [Color], ROW_NUMBER() OVER (ORDER BY [Id]) AS 'No' FROM #Foo ), cte2 AS ( SELECT [Value], ROW_NUMBER() OVER (ORDER BY [Value]) AS 'No' FROM #Bar ) SELECT [Id], [Color], [Value] FROM cte1 c1 FULL OUTER JOIN cte2 c2 ON c1.[No] = c2.[No]
Do you know faster or more standard way to do ZIP JOIN in T-SQL?
回答1:
You can simply try this.
;WITH CTE AS ( SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS Id, Value FROM #Bar ) SELECT F.Id, F.Color, CTE.Value FROM #Foo F LEFT JOIN CTE ON CTE.Id = F.Id
回答2:
You can get rid of the CTE
or make your query shorter
with subquery's like this
select Id,Color,Value from ( SELECT [Id], [Color], ROW_NUMBER() OVER (ORDER BY [Id]) AS 'No' FROM #Foo )x full outer join ( SELECT [Value], ROW_NUMBER() OVER (ORDER BY [Value]) AS 'No' FROM #Bar )y on x.No=y.No
回答3:
Will this suffice? (Admittedly, I may be miss-interpreting the question)
SELECT F.ID AS ID, F.Color AS Color, B.Value AS Value FROM #Foo F LEFT OUTER JOIN #Bar B ON F.ID = FLOOR(B.Value) --this DOES seem to return the correct output, but I'm not sure that my logic --is what you are after SELECT F.ID AS ID, F.Color AS Color, B.Value AS Value FROM ( VALUES (1,'Red'),(2,'Green'),(3,'Blue'),(4, NULL) ) AS F(ID, Color) LEFT OUTER JOIN ( VALUES (1), (2.5) ) AS B(Value) ON F.ID = FLOOR(B.Value)
Or are you wanting to essentially:
- Sort #Foo by ID
- Sort #Boo by Value
- Match:
- "First" row from #Foo with "First" row from #Bar
- "Second" row from #Foo with "Second" row from #Bar
- etc...
(Sorry, but I am not familiar with what a "ZIP JOIN" is. I will look at the link provided by @RszardDzegan, though.)
回答4:
you could try something like this:
DECLARE @Foo TABLE (Id INT, Color VARCHAR(10)); DECLARE @Bar TABLE (Value DECIMAL(2, 1)) INSERT INTO @Foo (Id, Color) VALUES (1, 'Red'), (2, 'Green'), (3, 'Blue'), (4, NULL) INSERT INTO @Bar (Value) VALUES (1), (2.5); WITH ECROSS AS ( SELECT F.Id, F.Color, B.Value, DENSE_RANK() OVER ( ORDER BY F.Id ) AS No1, DENSE_RANK() OVER ( ORDER BY B.Value ) AS No2 FROM @Foo F, @Bar B ) SELECT A.id, A.Color, B.Value FROM ECROSS A LEFT JOIN ECROSS B ON A.No1 = B.No2 AND A.No1 = B.No1 GROUP BY A.id, A.Color, B.Value
回答5:
DECLARE @Foo TABLE (pk_id int identity(1,1), Id INT, Color VARCHAR(10)); DECLARE @Bar TABLE (pk_id int identity(1,1), Value DECIMAL(2, 1)) INSERT INTO @Foo (Id, Color) VALUES (1, 'Red'), (2, 'Green'), (3, 'Blue'), (4, NULL) INSERT INTO @Bar (Value) VALUES (1), (2.5); SELECT F.id, F.Color, B.Value FROM @Foo F LEFT JOIN @Bar B ON F.pk_id = B.pk_id
回答6:
Try the following code. You just need to provide both data types in the same structure with a row number per group. With that you can use the PIVOT operator to produce the expected result.
WITH CTE_FOO AS ( SELECT [Group] ,[Spread] ,[Aggregate] FROM (VALUES (1, 1, N'Red' ) ,(2, 1, N'Green') ,(3, 1, N'Blue' ) ,(4, 1, NULL ) ) AS FOO([Group], [Spread], [Aggregate]) ), CTE_BAR AS ( SELECT [Group] ,[Spread] ,CAST([Aggregate] AS nvarchar(max)) AS [Aggregate] FROM (VALUES (1, 2, 1 ) ,(2, 2, 2.5 ) ) AS BAR([Group], [Spread], [Aggregate]) ), CTE_FOOBAR AS ( SELECT [Group], [Spread], [Aggregate] FROM CTE_FOO UNION ALL SELECT [Group], [Spread], [Aggregate] FROM CTE_BAR ) SELECT [Group] AS [ID] ,[1] AS [Color] ,[2] AS [Value] FROM CTE_FOOBAR PIVOT ( MAX([Aggregate]) FOR [Spread] IN ([1], [2]) ) AS PivotTable
回答7:
You can skip creating new row numbers for #Foo, since its row numbers in this case are given.
Then the solution will become
SELECT F.Id,F.Color,newBar.Value from #Foo as F LEFT JOIN ( SELECT [Value], ROW_NUMBER() OVER (ORDER BY [Value]) AS 'No' FROM #Bar ) newBar on F.Id=newBar.No
This solution has been tested and proven. It gives you all values of #Foo and for each a sorted value of #Bar if there is one.