sql - 使用来自另一个表的唯一值创建一个表

标签 sql sql-server

我正在使用 MS SQL Server Management Studio。我有 table -

+--------+----------+
| Num_ID | Alpha_ID |
+--------+----------+
|   1    |    A     |
|   1    |    B     |
|   1    |    C     |
|   2    |    B     |
|   2    |    C     |
|   3    |    A     |
|   4    |    C     |
|   5    |    A     |
|   5    |    B     |
+--------+----------+

我想从该表中创建另一个包含 2 列的表,以便 column_1 在 Num_ID 中提供唯一值(即 1、2、3、4 等),column_2 在 Alpha_ID 中提供唯一值(A、B、C 和很快)。

但是如果一个字母表已经出现过,它不应该再次出现。所以输出将是这样的 -

Col_1  Col_2
================
1     -    A
----------------
2     -    B
----------------
3      -   NULL (as A has been chosen by 1, it cannot occur next to 3)
----------------
4    -     C
----------------
5     -    NULL (both 5 A and 5 B cannot be chosen as A and B were picked up by 1 and 2) 
----------------

希望这是有道理的。 我想澄清一下,输入表中的 ID 不是我所显示的数字,而是 Num_ID 和 Alpha_ID 都是复杂的字符串。为了这个问题的目的,我将它们简化为 1,2,3,... 和 A, B, C ....

最佳答案

我不认为没有光标就可以做到这一点。 我在您的示例数据中添加了几行,以测试它如何适用于其他情况。

逻辑很简单。首先获取 Num_ID 所有不同值的列表。然后遍历它们并在每次迭代中向目标表添加一行。为了确定要添加的 Alpha_ID 值,我将使用 EXCEPT 运算符,它为当前 Num_ID 获取所有可用的 Alpha_ID 值> 从源表中删除之前使用过的所有值。

可以在不使用显式变量 @CurrAlphaID 的情况下编写 INSERT,但使用变量看起来更简洁一些。

这里是 SQL Fiddle .

DECLARE @TSrc TABLE (Num_ID varchar(10), Alpha_ID varchar(10));
INSERT INTO @TSrc (Num_ID, Alpha_ID) VALUES
('1', 'A'),
('1', 'B'),
('1', 'C'),
('2', 'B'),
('2', 'C'),
('3', 'A'),
('3', 'C'),
('4', 'A'),
('4', 'C'),
('5', 'A'),
('5', 'B'),
('5', 'C'),
('6', 'D'),
('6', 'E');

DECLARE @TDst TABLE (Num_ID varchar(10), Alpha_ID varchar(10));

DECLARE @CurrNumID varchar(10);
DECLARE @CurrAlphaID varchar(10);

DECLARE @iFS int;
DECLARE @VarCursor CURSOR;
SET @VarCursor = CURSOR FAST_FORWARD
FOR
    SELECT DISTINCT Num_ID
    FROM @TSrc
    ORDER BY Num_ID;

OPEN @VarCursor;

FETCH NEXT FROM @VarCursor INTO @CurrNumID;
SET @iFS = @@FETCH_STATUS;
WHILE @iFS = 0
BEGIN

    SET @CurrAlphaID = 
    (
        SELECT TOP(1) Diff.Alpha_ID
        FROM
            (
                SELECT Src.Alpha_ID
                FROM @TSrc AS Src
                WHERE Src.Num_ID = @CurrNumID

                EXCEPT

                SELECT Dst.Alpha_ID
                FROM @TDst AS Dst
            ) AS Diff
        ORDER BY Diff.Alpha_ID
    );

    INSERT INTO @TDst (Num_ID, Alpha_ID) 
    VALUES (@CurrNumID, @CurrAlphaID);

    FETCH NEXT FROM @VarCursor INTO @CurrNumID;
    SET @iFS = @@FETCH_STATUS;
END;

CLOSE @VarCursor;
DEALLOCATE @VarCursor;

SELECT * FROM @TDst;

结果

Num_ID    Alpha_ID
1         A
2         B
3         C
4         NULL
5         NULL
6         D

在源表的 (Num_ID, Alpha_ID) 上建立索引会有所帮助。在目标表的 (Alpha_ID) 上建立索引也会有所帮助。

关于sql - 使用来自另一个表的唯一值创建一个表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32389297/

相关文章:

c# - 如何将默认日期时间值与 SQL Server CE 和 Entity Framework 一起使用

android - 如何以最短时间查询数据库中的 3 个表

sql - 完全加入 MS Access

sql-server - 如何在 PowerShell 中返回对象的第二列/属性?

sql - 是否可以在主键不等于 column4 的表上写约束

sql-server - 如何在 SQL 语句中获取当前日期 + 4 小时?

sql - 使用WITH FORMAT备份SQL Server数据库

sql - 将一组行显示为单行

php - MySQL 数据库中的数据未更新。有什么想法吗?

sql - 删除 SQL Server 中的临时表?