类似于身份的列,但基于分组依据条件

Mar*_*c D 4 sql sql-server identity primary-key

在我的SQL Server 2012数据库中,我正在创建“任务”表,该表将具有由三个字段组成的复合主键:

Issue_ID [int] NOT NULL,
Issue_Sub_ID [int] NOT NULL,
Task_ID [int] NOT NULL
Run Code Online (Sandbox Code Playgroud)

Issue_ID并且Issue_Sub_ID是其他表的外键。在我创建的表中,每个Issue_ID/ Issue_Sub_ID组合可能有许多任务。

我想做的是为该Task_ID列建立一个默认值,这与我使用过的值类似IDENTITY(1,1),但是它将基于Issue_ID/ Issue_Sub_ID组自动增加。例如,Task_ID给定提供的Issue_ID/ Issue_Sub_ID值,结果将如下所示:

Issue_ID     Issue_Sub_ID     Task_ID
========     ============     =======
12345             1              1
12345             1              2
12345             1              3
12345             2              1
12345             2              2
67890             2              1
67890             2              2
67890             2              3
Run Code Online (Sandbox Code Playgroud)

我熟悉ROW_NUMBER() OVER(PARTITION BY Issue_ID, Issue_Sub_ID ORDER BY Issue_ID, Issue_Sub_ID)可能的解决方案,但是,由于我希望此列成为表的复合主键的一部分,所以我认为这行不通。

提前谢谢大家。

Zoh*_*led 6

我同意Sean的观点-添加一个identity列,然后仅使用一个计算列作为任务ID。尽管我已经回答的问题非常喜欢这一个在这里,我不知道这个标记作为一个重复。这样做的原因是您要将用task_id作主键的一部分。
但是,我不确定这是否可行,因为为了在主键中包含计算列,它必须是persisted,并且由于某种原因(我认为是因为使用了UDF),SQL Server不允许我标记坚持不懈。
无论如何,这是我为此建议的解决方案:

首先,创建一个将计算任务ID的函数:

CREATE FUNCTION dbo.GenerateTaskId
(
    @Row_Id int,
    @Issue_Id int,
    @Issue_Sub_Id int
)
RETURNS Int
AS
BEGIN

    RETURN 
    (
        SELECT COUNT(*)
        FROM dbo.Tasks
        WHERE Issue_Id = @Issue_Id
        AND Issue_Sub_ID = @Issue_Sub_ID
        AND Row_Id <= @Row_Id
    )
END
GO 
Run Code Online (Sandbox Code Playgroud)

然后,使用任务ID作为计算列创建表:

CREATE TABLE dbo.Tasks
(
    Row_Id [int] IDENTITY(1,1),
    Issue_ID [int] NOT NULL,
    Issue_Sub_ID [int] NOT NULL,
    Task_Id AS dbo.GenerateTaskId(Row_Id, Issue_Id, Issue_Sub_Id), 
    CONSTRAINT PK_Tasks PRIMARY KEY (Row_Id)
)
GO
Run Code Online (Sandbox Code Playgroud)

现在,对其进行测试:

INSERT INTO Tasks VALUES
(12345, 1),
(12345, 1),
(12345, 1),
(12345, 2),
(12345, 2),
(67890, 2),
(67890, 2),
(67890, 2)

SELECT *
FROM Tasks
Run Code Online (Sandbox Code Playgroud)

结果:

Row_Id  Issue_ID    Issue_Sub_ID    Task_Id
1       12345       1               1
2       12345       1               2
3       12345       1               3
4       12345       2               1
5       12345       2               2
6       67890       2               1
7       67890       2               2
8       67890       2               3
Run Code Online (Sandbox Code Playgroud)

您可以在rextester上观看现场演示。