【问题标题】:Create an instance of a table in a single row?在单行中创建表的实例?
【发布时间】:2019-06-03 17:26:06
【问题描述】:

当用户在 UI 中更新表格时,我无法弄清楚如何创建表格的快照(或实例)。

问题是:

我有一个用于“修正”的用户界面。在 UI 中,有一个“修正类型”的下拉列表。修正类型也有自己的用户界面,用户可以在此处选中/取消选中可用修正类型的列表。当用户取消选中修正类型时,该类型将从所有修正的下拉列表中删除。客户要求对修正类型的更改仅影响新修正,而不影响更改之前存在的修正。

因此,如果之前检查了“新建、草稿、已关闭”的修正类型值,并且未选中“草稿”,我仍然需要在 UI 中显示现有修正的所有三个值,然后只显示“新”和“已关闭”的新修订。但随后,他们可以返回并重新打开“草稿”并再次显示,但仅限于在重新打开后创建的修订。

对我来说,这意味着我需要为“修正类型历史”创建一个表。 “修正类型”表有一个修正类型 ID 列,其中所有 ID 都显示为行。我会将它们显示为列,行由生效日期定义——值更改的日期。然后我将 Amendment 链接到 AmendmentTypeHistoryID 并通过查找 AmendmentTypeID 来获取要显示的值。

例如

dbo.AmendmentType

AmendmentTypeID          Name         CreationDate       IsActive
      1                  New            6/2/2019            1
      2                  Draft          6/2/2019            1
      3                  Closed         6/2/2019            1

dbo.AmendmentTypeHistory

AmendmentTypeHistoryID     EffectiveDate     AmendmentTypeID     AmendmentTypeID     AmendmentTypeID
            1             6/3/2019           1 (New)             2 (Draft)               3 (Closed)

然后你改变它......

dbo.AmendmentType

AmendmentTypeID          Name         CreationDate       IsActive
      1                  New            6/2/2019            1
      3                  Closed         6/2/2019            1

dbo.AmendmentTypeHistory

AmendmentTypeHistoryID     EffectiveDate     AmendmentTypeID     AmendmentTypeID     AmendmentTypeID
            1             6/3/2019           1 (New)             2 (Draft)               3 (Closed)
            2             6/3/2019           1 (New)             3 (Closed)     NULL

总共有 77 种修正类型的可能性。这不是我可以硬编码的东西,所以我希望我能以某种方式动态地完成它。

有人知道我该怎么做吗?有没有更简单或更好的方法来做我想做的事情?

【问题讨论】:

    标签: sql sql-server asp.net-mvc tsql


    【解决方案1】:

    这是一个非常困难且令人困惑的要求。如果 IsActive 的修正类型在您将它们加载到下拉列表的那一刻和用户保存其条目的那一刻之间不同,会发生什么?

    忽略这一点,我会推荐一个表格,该表格将在有序的逗号分隔列表中映射组合。我的回答很少会打破范式,但否则会很困难。

    制作一个名为 AmendmentTypeGroup 的表:

    create table AmendmentTypeGroup
    (
    AmendmentTypeGroupID int identity
    ,AmendmentTypes nvarchar(max) not null
    ,constraint PK_AmendmentTypeGroup primary key clustered(AmendmentTypeGroupID)
    )
    

    在您的修正(非修正类型)表中添加一列:

    alter table Amendmends add AmendmentTypeGroupID int null
    

    每次在Amendments 中插入一行时,使用触发器或 proc 确保您首先将一组当前为 IsActive 的所有 AmendmentTypes 的 ID 插入到 AmendmentTypeGroup 中,获取组 ID,然后使用您插入的组值插入修正行。如果已经有一个具有特定组合的组,只需获取它的 id 并使用它。

    declare @amendmentCombination nvarchar(max)
    declare @groupID int
    select amendmentCombination=string_agg(convert(nvarchar(max),AmendmentTypeID),',') WITHIN GROUP ( ORDER BY AmendmentTypeID asc)
    from AmendmentType
    where IsActive = 1 -- will only work for sql server version 2017. Search XML path concatenation if you don't have it
    select @groupID=AmendmentTypeGroupID
    from AmendmentTypeGroup
    where AmendmentTypes=@amendmentCombination
    if @groupID is null
    begin
        insert AmendmentTypeGroup(AmendmentTypes) select @amendmentCombination
        set @groupID=SCOPE_IDENTITY() -- last id entered
    end
    
    insert Amendments(..your_other_columns...,AmendmentTypeGroup)
        select ..your_other_columns...,@groupID
    

    这样,对于每个 Amendment 行,您可以将其与 AmendmentTypeGroup 连接,以获取当时可用的 AmendmentTypes 的逗号分隔列表。您必须将其拆分为表格形式。

    为了使您的数据更加健壮,您应该 1) 手动创建用于修正中已存在行的所有 AmendmentTypeGroups,并将它们的 ID 插入 Amendment.AmendmentTypeGroup,这样您就可以 2) 在 Amendment 上创建一个 FK .AmendmentTypeGroup 引用 AmendmentTypeGroup.AmendmentTypeGroupID 3) 在 AmendmentTypeGroup.AmendmentTypes 上创建唯一约束

    如您所见,这很困难。小心行事。

    【讨论】:

      【解决方案2】:

      在你们遇到之后,我想我有一个解决方案。

      像这样创建一个表 AmendmentTypeVersions

      ID | VERSION_NUMBER | AmendmentTypeId
      

      并使用版本 1 插入所有活动的修正类型

      INSERT INTO AmendmentTypeVersions (VERSION_NUMBER ,  AmendmentTypeId)
          SELECT 1, AmendmentTypeID
          FROM AmendmentType
          WHERE isactive = 1
      

      每次保存AmendmentType,获取最大版本号并插入新版本的记录

      DECLARE @LastVersion = (SELECT MAX(VERSION_NUMBER) FROM AmendmentTypeVersions)
      
      INSERT INTO AmendmentTypeVersions (VERSION_NUMBER ,  AmendmentTypeId)
          SELECT @LastVersion + 1, AmendmentTypeID
          FROM AmendmentType
          WHERE isactive = 1
      

      使用 VERSION_NUMBER 添加到修正列并将其设置为 1

      现在你要做的就是:

      • 在创建修正时,您需要获取然后将修正 VERSION_NUMBER 设置为 @lastVersion(在编辑操作中,您已经设置了修正 VERSION_NUMBER)
      • 始终按修正案的 VERSION_NUMBER 过滤 AmendmentTypes(您必须按修正案的 VERSION_NUMBER 将修正案与 AmendmentTypeVersions 加入)

      【讨论】:

      • 我想到了,但是 IsActive 可以改变。他们仍然希望在更改之前创建的修正案可以选择“草案”,这是我的问题。我必须想办法知道在创建修正案时哪些标记为 IsActive。
      • 我认为您必须确定该要求。你所说的似乎是,当你创建一个新的修正时,只有活动的修正类型应该可用,但是当你编辑时,所有修正类型都可以选择。也许条件过滤器(取决于操作)可以解决问题。
      • 是的,我已经问过了,这就是他们想要的。如果他们检查了20个类型,然后又检查了20个并保存了它,保存之前所做的修改只能选择前20个。新的修改可以从40个中选择。然后他们进入并取消选中30并保存它。第一个修正案仍然可以选择 20,然后临时修正案可以选择 40,新的新修正案可以选择 10。我可以通过每次插入新的“新”或“草稿”类型并基于下拉菜单来做到这一点在日期范围内?它们有 77 种修正类型,我只是使用简单命名的作为示例。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-06-10
      • 1970-01-01
      • 2020-03-03
      • 1970-01-01
      • 2011-09-23
      • 1970-01-01
      • 2014-04-21
      相关资源
      最近更新 更多