如何在不使用表的情况下在SQL Server中执行连接

时间:2012-02-10 19:19:48

标签: sql sql-server sql-server-2008

我有两个列表,我想看看两个列表没有共同点。例如:

List1:
'a','b','c','123'

List2:
'd','e','f','a','asd','c'

我希望输出为:

'b','123','d','e','f','asd'

这样的东西?

select * from ('a','b','c','123')
join ('d','e','f','a','asd','c')
on ???

是否有一个纯SQL Server解决方案,而不使用表?

5 个答案:

答案 0 :(得分:5)

如果您可以控制列表,我只会将它们设为表变量:

DECLARE @a TABLE (str varchar(100))
INSERT INTO @a
VALUES
('a'),
('b')...

DECLARE @b table (str varchar(100))
INSERT INTO @b
VALUES
...

(SELECT str FROM @a
EXCEPT 
SELECT str FROM @b)
UNION
(SELECT str FROM @b
EXCEPT
SELECT str FROM @a)

答案 1 :(得分:3)

鉴于此功能:

CREATE FUNCTION dbo.SplitStrings ( @List NVARCHAR(MAX) )
RETURNS TABLE
AS
   RETURN ( SELECT Item FROM (
           SELECT Item = x.i.value('(./text())[1]', 'nvarchar(max)')
           FROM (
               SELECT [XML] = CONVERT(XML, '<i>' + REPLACE(@List,',', '</i><i>') 
                    + '</i>').query('.')) AS a CROSS APPLY [XML].nodes('i') AS x(i)
       ) AS y WHERE Item IS NOT NULL);
GO

您可以使用完整的外部联接:

DECLARE 
    @list1  NVARCHAR(MAX) = N'a,b,c,123', 
    @list2  NVARCHAR(MAX) = N'd,e,f,a,asd,c',
    @output NVARCHAR(MAX) = N'';

SELECT @output += N',' + COALESCE(l1.Item, l2.Item) 
  FROM dbo.SplitStrings(@list1) AS l1
  FULL OUTER JOIN dbo.SplitStrings(@list2) AS l2
  ON l1.Item = l2.Item 
  WHERE l1.Item IS NULL OR l2.Item IS NULL;

SELECT STUFF(@output, 1, 1, N'');

或类似于@ JNK:

DECLARE 
    @list1  NVARCHAR(MAX) = N'a,b,c,123', 
    @list2  NVARCHAR(MAX) = N'd,e,f,a,asd,c',
    @output NVARCHAR(MAX) = N'';

;WITH l1 AS (SELECT Item FROM dbo.SplitStrings(@list1)), 
      l2 AS (SELECT Item FROM dbo.SplitStrings(@list2))
SELECT @output += N',' + Item 
FROM ( (SELECT Item FROM l1 EXCEPT SELECT Item FROM l2)
        UNION
       (SELECT Item FROM l2 EXCEPT SELECT Item FROM l1)) AS x;

SELECT STUFF(@output, 1, 1, N'');

也许还有其他各种方式。如果订单很重要,它会变得更复杂,但仍然可能。

答案 2 :(得分:1)

没有简单的方法来实现这一目标。要过滤列表中的值,您需要将它们作为行。所以你最终会得到类似的东西:

SELECT col FROM (
SELECT 'a' as col
UNION
SELECT 'b'
UNION
SELECT 'c') t

WHERE col NOT IN ('a', 'b')

答案 3 :(得分:1)

怎么样:

with
list1(j) as (select 'a' union select 'b'),
list2(j) as (select 'b' union select 'c')

select coalesce(list1.j, list2.j)
from list1 full join list2
on list1.j = list2.j
where (list1.j is null or list2.j is null)

答案 4 :(得分:0)

我认为您必须将值插入2个变量表中。

DECLARE @Table1 TABLE (Value VARCHAR(1))
DECLARE @Table2 TABLE (Value VARCHAR(1))

INSERT INTO @Table1 (Value) VALUES ('a')
INSERT INTO @Table1 (Value) VALUES ('b')

INSERT INTO @Table2 (Value) VALUES ('b')
INSERT INTO @Table2 (Value) VALUES ('c')

然后对2个表执行一些设置操作。

DECLARE @TableUnion TABLE (Value VARCHAR(1))
DECLARE @TableIntersection TABLE (Value VARCHAR(1))
DECLARE @TableExcept TABLE (Value VARCHAR(1))

INSERT INTO @TableUnion 
SELECT * FROM
    ((SELECT * FROM @Table1)
    UNION
    (SELECT * FROM @Table2)) U

INSERT INTO @TableIntersection 
SELECT * FROM
    ((SELECT * FROM @Table1)
    INTERSECT
    (SELECT * FROM @Table2)) I

INSERT INTO @TableExcept
SELECT * FROM
    ((SELECT * FROM @TableUnion)
    EXCEPT
    (SELECT * FROM @TableIntersection)) E

最终select语句的结果集将包含'a'和'c'。哪个可以连接成一个字符串,如下所示。

DECLARE @ExceptString VARCHAR(3)

SELECT @ExceptString = 
    CASE 
        WHEN @ExceptString IS NULL THEN Value
        ELSE @ExceptString + ',' + Value
    END
FROM @TableExcept