循环记录并根据条件更新数据库

Posted

技术标签:

【中文标题】循环记录并根据条件更新数据库【英文标题】:Loop through records and update database on conditions 【发布时间】:2016-12-30 19:50:04 【问题描述】:

我有一张桌子Person

其中ID是主键,Male是男性总数,Female是女性总数,Person_ID列固定为4,所以男性+女性的最大数量是4 (我们不必对此进行验证)。

我需要将YesNo 的最后一列Is_Valid 值插入/更新,以确定记录是否有效。

逻辑如下:例如男性和女性的总数为 3,则必须有 3 个人员 ID,或者如果男性和女性的总数为 2,则必须有 2 个人员 ID 数据。

所以记录 ID 3 和 4 是无效的,因为记录 3 - 有 2 人(1 男 1 女)但只有 1 人 ID,记录 4 有 1 人(1 女)但没有人ID 数据。

我需要在 c# 代码中以编程方式执行此操作,但首先我想知道可以解决此问题的查询?

我一直在想的逻辑是:

遍历每一行 得到男性 + 女性的总和 = a 以某种方式计算非空人员 ID 单元格 = b 如果 a == b 则插入 YES,否则插入 NO

我不知道如何编写查询(或存储过程),我想它会有点复杂。任何帮助将不胜感激。

【问题讨论】:

personid列是固定4列吗? @ShakeerMirza 是的 我认为如果您对数据进行规范化会更好,这样您就可以拥有一个主表和一个辅助表,而不是四个 Person_Id 列,其中包含以下列:Id、fkey to primary表,男(位),女(位),Person_Id。然后所有四个(或许多)记录将指向主表中的同一记录。像这样固定所有值后,当您决定需要五个 Person_Id 时,您必须同时修改架构和查询。否则,Long 的答案应该有效。 【参考方案1】:
UPDATE TABLE
SET Is_Valid = CASE WHEN (
               Case when Person1_ID != '' or Person1_ID IS NOT NULL Then 1 else 0 end +
               Case when Person2_ID != '' or Person2_ID IS NOT NULL Then 1 else 0 end +
               Case when Person3_ID != '' or Person3_ID IS NOT NULL Then 1 else 0 end +
               Case when Person4_ID != '' or Person4_ID IS NOT NULL Then 1 else 0 end ) != Male + Female THEN 'NO' ELSE 'YES' END

【讨论】:

试试这个查询,不确定它是否工作正常,因为我没有你的表,如果有任何运行时问题,请更新我 -【参考方案2】:
CREATE TABLE #Demo   
(   
id integer not null primary key,
male integer NULL,   
female integer NULL,   
PersonId_1 integer null,
PersonId_2 integer null,   
PersonId_3 integer null,
PersonId_4 integer null,
IsValid bit not null
);  

insert into #Demo
(id, male, female, PersonId_1,PersonId_2,PersonId_3,PersonId_4,IsValid)
values
(1,1,1,2,2,null,null,0)

update #Demo
set IsValid = 1
where (#Demo.male + #Demo.female) = 
(case when #Demo.PersonId_1 IS NOT NULL Then 1 Else 0 end)+
(case when #Demo.PersonId_2 IS NOT NULL Then 1 Else 0 end)+
(case when #Demo.PersonId_3 IS NOT NULL Then 1 Else 0 end)+
(case when #Demo.PersonId_4 IS NOT NULL Then 1 Else 0 end)

select * from #Demo

【讨论】:

【参考方案3】:

您可以为此运行更新语句,而不必遍历它。或者您可以将 is_valid 设为计算列。

DECLARE @test TABLE (
id INT IDENTITY(1,1)
,male INT
,female INT
,person1_id INT
,person2_id INT
,person3_id INT
,person4_id INT
,is_valid AS CASE
    WHEN  (male + female = 1 AND person1_id IS NOT NULL AND person2_id IS NULL AND person3_id IS NULL AND person4_id IS NULL)
        OR (male + female = 2 AND person1_id IS NOT NULL AND person2_id IS NOT NULL AND person3_id IS NULL AND person4_id IS NULL)
        OR (male + female = 3 AND person1_id IS NOT NULL AND person2_id IS NOT NULL AND person3_id IS NULL AND person4_id IS NULL)
        OR (male + female = 4 AND person1_id IS NOT NULL AND person2_id IS NOT NULL AND person3_id IS NOT NULL AND person4_id IS NULL)
    THEN 1
    ELSE 0
    END
)

INSERT @test (male,female,person1_id,person2_id,person3_id,person4_id)
VALUES
(1,1,200,700,NULL,NULL)
,(2,0,205,210,NULL,NULL)
,(1,1,240,NULL,NULL,NULL)
,(0,1,NULL,NULL,NULL,NULL)

SELECT * FROM @test

【讨论】:

【参考方案4】:

添加Male + Female 列值并将它们与具有非空值或空值的列数进行比较。如果它们相等,则将Is_Valid 设置为 1,否则将其设置为 0。

update p
set Is_Valid =
                case
                    when Male + Female = (iif(Isnull(Person1_ID, '') = '', 0, 1) + iif(Isnull(Person2_ID, '') = '', 0, 1) +
                        iif(Isnull(Person3_ID, '') = '', 0, 1) + iif(Isnull(Person4_ID, '') = '', 0, 1)) then 'YES'
                    else 'NO'
                end

from Person p

只是为了澄清下面的代码检查该列是否具有空值并将其设为空,然后检查它是否为空,如果是则将其设为 0,否则将其设为 1。这是针对每一列完成的:

iif(Isnull(Person1_ID, '') = '', 0, 1)

您也可以这样做以更加小心并检查空格:

iif(Isnull(rtrim(ltrim(Person1_ID))), '') = '', 0, 1)

【讨论】:

【参考方案5】:

无需循环

;WITH CTE
AS (
    SELECT id
        ,CASE 
            WHEN (male + female) = isnull(personid_1 / personid_1, 0) 
                                  + isnull(personid_2 / personid_2, 0)
                                  + isnull(personid_3 / personid_3, 0)
                                  + isnull(personid_4 / personid_4, 0)
                THEN 'Yes'
            ELSE 'No'
            END AS valid
    FROM PERSON
    )
UPDATE PERSON
SET IS_VALID = CTE.VALID
FROM CTE
WHERE PERSON.ID = CTE.ID

【讨论】:

以上是关于循环记录并根据条件更新数据库的主要内容,如果未能解决你的问题,请参考以下文章

雄辩的条件更新

循环访问 Access 中的两个记录集并更新条目

forEach 循环没有根据需要更新数组

Spring-batch - 比较来自 csv 的数据并相应地更新 Salesforce 中的记录

MySQL中批量更新 | case when 进行数据批量更新

根据条件更改 ActionBar 中的图标