我有一个包含 5 列 (
A1,A2,A3,A4,A5
) 的数据库,其中存储 5 个数字。
这 5 个数字是
"1,2,3,4,5"
。
A1 A2 A3 A4 A5
-------------------------------
2 4 5 Null Null
我想得到丢失的数字“1”和“3”。 如何从5个号码中找出缺失的号码?
Select Replace(Replace(Replace(Replace(
Replace('12345',(Cast(Coalesce(A5,0) as varchar(1))),''),
(Cast(Coalesce(A4,0) as varchar(1))),''),
(Cast(Coalesce(A3,0) as varchar(1))),''),
(Cast(Coalesce(A2,0) as varchar(1))),''),
(Cast(Coalesce(A1,0) as varchar(1))),'') from Table1
你可以这样做
WITH sequence AS
(
SELECT 1 n UNION ALL
SELECT n + 1 FROM sequence WHERE n < 5
)
SELECT n
FROM sequence s LEFT JOIN table1 t
ON s.n IN (t.a1, t.a2, t.a3, t.a4, t.a5)
WHERE t.a1 IS NULL
输出:
|尼 | |---| | 1 | | 3 |
这里是SQLFiddle演示
一个优雅的解决方案可以扩展到您问题中提供的 5 个值之外,它使用了数字表(如链接所示,数字表对于多种任务来说是无价的)。
这是数字表的设置,在本例中限制为 256 个数字,因为您在问题中使用的范围很小。
/*
create a numbers table with numbers from 0 to
255 (the range of the tinyint data type).
*/
DROP TABLE IF EXISTS [#numbers];
GO
CREATE TABLE [#numbers]
(
[n] tinyint NOT NULL
);
WITH [numbers]
AS
(
SELECT [v].[n]
FROM
(
VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9)
) [v]([n])
)
INSERT INTO [#numbers]
(
[n]
)
SELECT TOP(255)
[number] =
([n1].[n] * 100)
+ ([n2].[n] * 10)
+ ([n3].[n] * 1)
FROM
[numbers] [n1]
CROSS JOIN [numbers] [n2]
CROSS JOIN [numbers] [n3]
ORDER BY
([n1].[n] * 100)
+ ([n2].[n] * 10)
+ ([n3].[n] * 1);
接下来,我们将创建您在问题中提到的表:
DROP TABLE IF EXISTS [#rows];
CREATE TABLE [#rows]
(
[a1] tinyint NULL
, [a2] tinyint NULL
, [a3] tinyint NULL
, [a4] tinyint NULL
, [a5] tinyint NULL
);
在这里,我们用您的值填充该行:
INSERT INTO [#rows] ([a1], [a2], [a3])
VALUES (2, 4, 5);
[#rows]
表的内容:
a1 | a2 | a3 | a4 | a5 |
---|---|---|---|---|
2 | 4 | 5 | 空 | 空 |
我将使用 UNPIVOT 子句 将列转换为行。为了清楚起见,这就是
UNPIVOT
本身的样子:
SELECT
[upv].[value]
FROM
(
SELECT *
FROM [#rows]
) [src]
UNPIVOT
(
[value] FOR [column] IN ([a1], [a2], [a3], [a4], [a5])
) [upv]
ORDER BY
[upv].[value];
UNPIVOT
查询的中间结果:
价值 |
---|
2 |
4 |
5 |
如您所见,我们缺少值
1
和 3
。在这里,我们通过将 UNPIVOT
的结果与 EXCEPT T-SQL 运算符 与 [#numbers]
表相结合来显示缺失值:
SELECT
[missing_number] = [n].[n]
FROM
[#numbers] [n]
WHERE
[n].[n] > 0
AND [n].[n] <= 5
EXCEPT
SELECT
[upv].[value]
FROM
(
SELECT *
FROM [#rows]
) [src]
UNPIVOT
(
[value] FOR [column] IN ([a1], [a2], [a3], [a4], [a5])
) [upv];
EXCEPT
运算符显示了运算符左侧的不同结果,而运算符右侧的结果中不存在这些结果。结果是:
缺少号码 |
---|
1 |
3 |
您需要一个从 1 到(在本例中)5 的整数表:
DECLARE @ints table (n int);
INSERT @ints VALUES (1), (2), (3), (4), (5);
其次,我们将表行中的数字放入一个可比较的集合中:
SELECT x INTO #all FROM (
SELECT A1 as x FROM myTable WHERE ID = myRow
UNION ALL
SELECT A2 as x FROM myTable WHERE ID = myRow
UNION ALL
SELECT A3 as x FROM myTable WHERE ID = myRow
UNION ALL
SELECT A4 as x FROM myTable WHERE ID = myRow
UNION ALL
SELECT A5 as x FROM myTable WHERE ID = myRow
) y
那么你就可以得出答案:
SELECT @ints.n
FROM @ints left join #all on @ints.n = #all.x
WHERE #all.x is null
ORDER BY 1