从非序列号中查找缺失的号码

问题描述 投票:0回答:4

我有一个包含 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个号码中找出缺失的号码?

sql sql-server vb.net
4个回答
2
投票
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

Sql Fiddle 演示


2
投票

你可以这样做

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演示


1
投票

一个优雅的解决方案可以扩展到您问题中提供的 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

0
投票

您需要一个从 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
© www.soinside.com 2019 - 2024. All rights reserved.