Intersection in SQL Server

Is there a way to use intersection without selecting only individual values? Something like INTERSECT ALL .

For example, consider tables A and B

 A --> 1, 1, 1, 2, 3, 4 B --> 1, 1, 2 

Result

 Result --> 1, 1, 2 

EDIT

I think the link explains what I want. This other link also interests the question. Or this other link explains the event better.

EDIT 2

Suppose the tables are:

Table a

 ╔════════╦════╦═══╦════╦════╗ β•‘ A β•‘ B β•‘ C β•‘ D β•‘ E β•‘ ╠════════╬════╬═══╬════╬════╣ β•‘ Car β•‘ 10 β•‘ 1 β•‘ OK β•‘ -1 β•‘ β•‘ Car β•‘ 10 β•‘ 1 β•‘ OK β•‘ -1 β•‘ β•‘ Car β•‘ 10 β•‘ 1 β•‘ OK β•‘ -1 β•‘ β•‘ House β•‘ 10 β•‘ 1 β•‘ NO β•‘ -5 β•‘ β•‘ Monkey β•‘ 15 β•‘ 1 β•‘ OK β•‘ -1 β•‘ β•‘ Dog β•‘ 3 β•‘ 1 β•‘ OK β•‘ -1 β•‘ β•šβ•β•β•β•β•β•β•β•β•©β•β•β•β•β•©β•β•β•β•©β•β•β•β•β•©β•β•β•β•β• 

Table B

 ╔═════╦════╦═══╦════╦════╗ β•‘ A β•‘ B β•‘ C β•‘ D β•‘ E β•‘ ╠═════╬════╬═══╬════╬════╣ β•‘ Car β•‘ 10 β•‘ 1 β•‘ OK β•‘ -1 β•‘ β•‘ Car β•‘ 10 β•‘ 1 β•‘ OK β•‘ -1 β•‘ β•‘ Car β•‘ 15 β•‘ 1 β•‘ OK β•‘ -1 β•‘ β•‘ Dog β•‘ 3 β•‘ 1 β•‘ OK β•‘ -1 β•‘ β•šβ•β•β•β•β•β•©β•β•β•β•β•©β•β•β•β•©β•β•β•β•β•©β•β•β•β•β• 

The answer for the intersection ( select * from A INTERSECT select * from B ) will be as follows:

 ╔═════╦════╦═══╦════╦════╗ β•‘ A β•‘ B β•‘ C β•‘ D β•‘ E β•‘ ╠═════╬════╬═══╬════╬════╣ β•‘ Car β•‘ 10 β•‘ 1 β•‘ OK β•‘ -1 β•‘ β•‘ Dog β•‘ 3 β•‘ 1 β•‘ OK β•‘ -1 β•‘ β•šβ•β•β•β•β•β•©β•β•β•β•β•©β•β•β•β•©β•β•β•β•β•©β•β•β•β•β• 

Because it takes only different meanings. I want to use generic lines, like:

 ╔═════╦════╦═══╦════╦════╗ β•‘ A β•‘ B β•‘ C β•‘ D β•‘ E β•‘ ╠═════╬════╬═══╬════╬════╣ β•‘ Car β•‘ 10 β•‘ 1 β•‘ OK β•‘ -1 β•‘ β•‘ Car β•‘ 10 β•‘ 1 β•‘ OK β•‘ -1 β•‘ β•‘ Dog β•‘ 3 β•‘ 1 β•‘ OK β•‘ -1 β•‘ β•šβ•β•β•β•β•β•©β•β•β•β•β•©β•β•β•β•©β•β•β•β•β•©β•β•β•β•β• 

Please note: I do not need to know what I need to bind (the connection is positional, like INTERSECT ). The identifier will be built using all columns (the relationship between the table is all columns based on their position).

+5
source share
3 answers

In SQL Server, INTERSECT only works with single rows. If you want it to distinguish between repeated lines, you will need to make the lines different. The only way I can think of this is to add another column and fill it with unique values ​​for each duplicate, but in such a way that the resulting rows are comparable in different tables.

The problem, however, is that there is still no universal syntax for this. For example, you can use ROW_NUMBER () to list each duplicate, but you will have to write its PARTITION BY clause for each case separately: there is no PARTITION BY * , not SQL Server, at least.

In any case, for the purpose of illustration, here is how the ROW_NUMBER method looks:

 SELECT A, B, C, D, E, ROW_NUMBER() OVER (PARTITION BY A, B, C, D, E ORDER BY (SELECT 1)) FROM dbo.A INTERSECT SELECT A, B, C, D, E, ROW_NUMBER() OVER (PARTITION BY A, B, C, D, E ORDER BY (SELECT 1)) FROM dbo.B ; 

As written above, the query will also return an extra column, a row number column, in the output. If you want to suppress it, you need to make the request more complex:

 SELECT A, B, C, D, E FROM ( SELECT A, B, C, D, E, rn = ROW_NUMBER() OVER (PARTITION BY A, B, C, D, E ORDER BY (SELECT 1)) FROM dbo.A INTERSECT SELECT A, B, C, D, E, rn = ROW_NUMBER() OVER (PARTITION BY A, B, C, D, E ORDER BY (SELECT 1)) FROM dbo.B ) AS s ; 

And just for clarification, when I said above, there was no universal syntax, I meant that you could not do this without resorting to dynamic SQL. With dynamic SQL, a lot of things are possible, but such a solution will be much more complex and, in my opinion, much less convenient.

Again, to illustrate this point, this is an example of how you could solve it using dynamic SQL:

 DECLARE @table1 sysname, @table2 sysname, @columns nvarchar(max), @sql nvarchar(max) ; SET @table1 = 'dbo.A'; SET @table2 = 'dbo.B'; -- collecting the columns from one table only, -- assuming the structures of both tables are identical -- if the structures differ, declare and populate -- @columns1 and @columns2 separately SET @columns = STUFF( ( SELECT N', ' + QUOTENAME(name) FROM sys.columns WHERE object_id = OBJECT_ID(@table1) FOR XML PATH (''), TYPE ).value('text()[1]', 'nvarchar(max)'), 1, 2, '' ); SET @sql = N'SELECT ' + @columns + N' FROM ( SELECT ' + @columns + N', ROW_NUMBER() OVER (PARTITION BY ' + @columns + N' ORDER BY (SELECT 1)) FROM ' + @table1 + N' INTERSECT SELECT ' + @columns + N', ROW_NUMBER() OVER (PARTITION BY ' + @columns + N' ORDER BY (SELECT 1)) FROM ' + @table2 + N' ) AS s '; EXECUTE sp_executesql @sql; 

You can probably see now what I meant by β€œmuch more complex,” at least.

+5
source
 SELECT COLUMN1 FROM B WHERE B.COLUMN1 IN (SELECT COLUMN1 FROM A) 
0
source
 SELECT * FROM TableB WHERE EXISTS (SELECT 1 FROM TableA WHERE ColumnName = TableB.ColumnName) 
0
source

Source: https://habr.com/ru/post/1202907/


All Articles