You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:为主任务与子任务生成连续唯一TaskId的SQL实现

解决方案:为主任务和子任务生成连续关联的TaskId

核心思路

要实现主TaskId连续、子TaskId紧跟所属主TaskId的需求,不能单纯依赖全局ROW_NUMBER(),而是需要先计算每个主任务及其子任务的总数量,再通过累计求和确定每个主任务的起始ID,最后为子任务分配后续连续ID。

SQL实现方案

假设你的数据库结构如下:

  • MainTasks:主任务表,包含Id(主键)、Title等字段
  • SubTasks:子任务表,包含Id(主键)、MainTaskId(关联主任务)、Title等字段

以下是完整的SQL查询代码:

WITH MainTaskCounts AS (
    SELECT 
        mt.Id AS MainTaskId,
        mt.Title,
        -- 统计当前主任务的总任务数(自身1条 + 关联子任务数)
        1 + COUNT(st.Id) AS TotalTasks
    FROM MainTasks mt
    LEFT JOIN SubTasks st ON mt.Id = st.MainTaskId
    GROUP BY mt.Id, mt.Title
),
MainTaskStartIds AS (
    SELECT 
        MainTaskId,
        Title,
        TotalTasks,
        -- 计算当前主任务的起始TaskId:前面所有主任务的总任务数之和 + 1
        COALESCE(SUM(TotalTasks) OVER(ORDER BY MainTaskId ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING), 0) + 1 AS StartTaskId
    FROM MainTaskCounts
    ORDER BY MainTaskId
),
MainTasksWithTaskId AS (
    SELECT 
        StartTaskId AS TaskId,
        MainTaskId AS OriginalTaskId,
        Title,
        NULL AS ParentTaskId
        -- 补充Gantt需要的其他字段:StartDate, EndDate, Duration等
    FROM MainTaskStartIds
),
SubTasksWithTaskId AS (
    SELECT 
        -- 子任务的TaskId = 所属主任务的起始ID + 子任务的排序序号
        mts.StartTaskId + ROW_NUMBER() OVER(PARTITION BY st.MainTaskId ORDER BY st.Id) AS TaskId,
        st.Id AS OriginalTaskId,
        st.Title,
        mts.StartTaskId AS ParentTaskId
        -- 补充Gantt需要的其他字段:StartDate, EndDate, Duration等
    FROM SubTasks st
    INNER JOIN MainTaskStartIds mts ON st.MainTaskId = mts.MainTaskId
)
-- 合并主任务和子任务结果,按TaskId排序
SELECT * FROM MainTasksWithTaskId
UNION ALL
SELECT * FROM SubTasksWithTaskId
ORDER BY TaskId;

代码逻辑说明

  1. MainTaskCounts:统计每个主任务包含的总任务数(自身1条加上关联的子任务数量)。
  2. MainTaskStartIds:使用窗口函数SUM() OVER()计算每个主任务的起始TaskId,第一个主任务的起始ID为1,后续主任务的起始ID为前面所有主任务总任务数之和加1。
  3. MainTasksWithTaskId:将主任务的起始ID作为其TaskId,ParentTaskId设为NULL(表示无父任务)。
  4. SubTasksWithTaskId:为每个子任务分配TaskId,规则是所属主任务的起始ID加上子任务在该主任务下的排序序号,ParentTaskId设为主任务的TaskId。

Syncfusion Blazor Gantt 适配

C#实体类定义

根据Gantt图表的要求,定义对应的任务实体:

public class GanttTask
{
    public int TaskId { get; set; }
    public string Title { get; set; }
    public int? ParentTaskId { get; set; }
    // 根据Gantt需求添加其他字段:StartDate, EndDate, Duration, Progress等
}

API端点实现

在你的后端API中执行上述SQL,将结果映射到实体类后返回给前端:

using Dapper;
using Microsoft.AspNetCore.Mvc;
using System.Data.SqlClient;

[ApiController]
[Route("api/[controller]")]
public class GanttTasksController : ControllerBase
{
    private readonly IConfiguration _configuration;

    public GanttTasksController(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    [HttpGet]
    public async Task<IActionResult> GetTasks()
    {
        var sql = @"
            -- 粘贴上面的完整SQL语句
        ";

        using var connection = new SqlConnection(_configuration.GetConnectionString("DefaultConnection"));
        var tasks = await connection.QueryAsync<GanttTask>(sql);
        
        return Ok(tasks);
    }
}

期望输出示例

以你描述的5个主任务场景为例,最终输出的TaskId序列如下:

TaskIdTitleParentTaskId
1主任务1NULL
2子任务1-11
3子任务1-21
4子任务1-31
5主任务2NULL
6子任务2-15
7子任务2-25
8主任务3NULL
9主任务4NULL
10主任务5NULL

内容的提问来源于stack exchange,提问作者M.Bouabdallah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 10:05:15