如何在不使用表的情况下在SQL Server中执行联接
我有两个列表,我想看看这两个列表没有什么共同点。例如:如何在不使用表的情况下在SQL Server中执行联接,sql,sql-server,sql-server-2008,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解决方案?实现这一点没有简单的方法。要从列表中筛
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解决方案?实现这一点没有简单的方法。要从列表中筛选值,需要将它们作为行。所以你会得到这样的结果:
SELECT col FROM (
SELECT 'a' as col
UNION
SELECT 'b'
UNION
SELECT 'c') t
WHERE col NOT IN ('a', 'b')
要做到这一点并不容易。要从列表中筛选值,需要将它们作为行。所以你会得到这样的结果:
SELECT col FROM (
SELECT 'a' as col
UNION
SELECT 'b'
UNION
SELECT 'c') t
WHERE col NOT IN ('a', 'b')
如果您可以控制列表,我只需要将它们设置为表变量:
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)
如果您可以控制列表,我只需要将它们设置为表变量:
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)
那么:
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)
那么:
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)
我认为您必须将这些值插入到两个变量表中
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')
然后对这两个表执行一些设置操作
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
我认为您必须将这些值插入到两个变量表中
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')
然后对这两个表执行一些设置操作
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
鉴于此功能:
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
或类似于@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'');
可能还有其他各种方式。如果顺序很重要,它会稍微复杂一点,但仍然是可能的。给定此函数:
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
或类似于@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'');
可能还有其他各种方式。如果顺序很重要,它会稍微复杂一点,但仍然是可能的。这些列表在您的查询中是硬编码的吗?@stevepastelan是的,它们确实是输出需要是六个独立的列还是可以是字符串?@AaronBertrand string很好!!您是否可以控制列表的脚本编写方式?这些列表在您的查询中是否硬编码?@stevepastelan是的,它们确实是输出需要是六个独立的列还是可以是字符串?@AaronBertrand string很好!!你可以控制列表的脚本编写方式吗?你可能可以使用拆分函数或其他方法将它们作为字符串处理,但我认为这将是最简单的。你对stevepalen Answers有何看法?我认为这不是编译:)他在两个CTE中插入一行,因此它可能也可以工作,但是在每一行之间使用
并集
的语法需要更难看。为什么要使用EXCEPT而不是join?它是一个集合比较运算符,语法更简单。你可以做几个连接来获得相同的效果,但这更简单。你可以使用拆分函数或其他方法将它们作为字符串处理,但我认为这是最简单的。你对stevepalen Answers有什么看法我认为它不编译:)他在两个CTE中插入一行,因此,它可能也可以工作,但它需要更难看的语法,在每行之间使用并集,为什么使用EXCEPT而不是join?它是一个集合比较运算符,语法更简单。你可能会做一些JOIN
s来获得同样的效果,但这更简单。Msg 156,级别15,状态1,第3行关键字“values”附近的语法不正确。steve你能让它编译吗"? JNK说他将一行插入到两个CTE中,因此它可能也能工作,但需要使用更难看的语法,在每行之间使用并集,这太糟糕了。我手头没有SQL Server,但它是在DB2上运行的。我希望语法是兼容的:)@stevepastelan如果你将值
语句更改为选择“a”联合选择“b”联合…
它应该解析OK。Msg 156,级别15,状态1,第3行关键字“值”附近的语法不正确。steve你能让它编译吗"? JNK说他将一行插入到两个CTE中,因此它可能也能工作,但需要使用更难看的语法,在每行之间使用并集,这太糟糕了。我手头没有SQL Server,但它是在DB2上运行的。我希望语法是兼容的:)@stevepastelan如果您将值
语句更改为select'a'union选择'b'union…
它应该解析OK.+1以进行补偿,尽管您的输出不是与请求相反吗?不。他想要两个列表的异或。不过,感谢同情的投票:-)他说他希望输出是'b','123','d','e','f','asd'
而不是'a','c'
。。。他还希望它们是一个字符串,而不是一列中的两个值。集合1由{'a','b'}组成,集合2由{'b','c'}组成。这两个集合的异或是{'a','c'}。将这些值连接回一个字符串是很简单的,但如果需要,我可以添加它。啊,对不起。我认为,一般来说,使用与OP相同的数据更有用,尤其是当您缩减的数据恰好与要求相矛盾时(可能将其更改为apple、bear、cat
以区分)。+1以补偿,尽管您的输出不是与要求相反吗?不。他想要两个列表的异或。不过,感谢同情的投票:-)他说他希望输出是'b','123','d','e','f','asd'
而不是'a','c'
。。。他还希望它们是一个字符串,而不是一列中的两个值。集合1由{'a','b'}组成,集合2由{'b','c'}组成。这两个集合的异或是{'a','c'}。将这些值连接回一个字符串是很简单的,但如果需要,我可以添加它。啊,对不起。一般来说,我认为使用与OP相同的数据更有用,尤其是当您缩减的数据与要求相矛盾时(可能会将其更改为apple、bear、cat
,以区分)。您为什么使用EXCEPT而不是join?抱歉,交换了代码示例,仅此而已。我只写了所有的东西,除了函数w