【问题标题】:Update multiple records based on 1 record meeting a criteria根据符合条件的 1 条记录更新多条记录
【发布时间】:2019-10-29 18:48:25
【问题描述】:

我正在尝试从其中 1 条记录符合条件的数据集中选择所有记录。我有一个数据表,其中包含一个人每天工作的时间。如果该周内的一条记录的“已记录”标志设置为“N”,我需要选择该周某人的所有记录。这是一个数据示例:

t_hours:

Name  Week  Weekday  Hours  Logged
===============================
Jim   1     Mon      8       Y
Jim   1     Wed      8       Y
Jim   1     Fri      8       Y
Jim   2     Mon      8       Y
Jim   2     Wed      8       Y
Bill  1     Mon      8       N
Bill  1     Tue      8       Y
Bill  1     Wed      8       Y
Bill  1     Thu      8       Y
Bill  2     Mon      8       Y
Bill  2     Tue      8       Y

我想编写一个查询,如果他们有一天 Logged='N',则将一个人工作周的所有记录更新为 Logged='N'。但我不知道如何选择记录。以下是我要更新的记录:

Name  Week  Weekday  Hours  Logged
===============================
Bill  1     Mon      8       N
Bill  1     Tue      8       Y
Bill  1     Wed      8       Y
Bill  1     Thu      8       Y

我尝试了一个普通的选择,但不知道如何在 where 子句中有两个相关的子查询:

SELECT * FROM t_hours
WHERE (Name = (SELECT t1.Name FROM t_hours t1 
               where t1.Name = t2.Name and t1.Week = t2.Week and 
               t1.Logged = 'N') and
       Week = (SELECT t2.Week FROM t_hours t2 
               where t1.Name = t2.Name and t1.Week = t2.Week and 
               t2.Logged = 'N')

但这不起作用,非常感谢任何帮助。

【问题讨论】:

    标签: sql sql-server where-clause correlated-subquery


    【解决方案1】:

    您可以使用可更新的 CTE:

    with toupdate as (
          select t.*,
                 min(logged) over (partition by name, week) as min_logged
          from t
         )
    update toupdate
        set logged = min_logged
        where min_logged = 'N' and min_logged <> logged;
    

    如果个人/周的任何logged 值是'N'(其余如果有的话是'Y'),则min(logged) 表达式将返回'N'

    【讨论】:

    • 这是一个非常干净的答案,戈登。 min_logged 是否仅起作用,因为有两个选项,例如N/Y,或者如果有附加值,它仍然有效吗?我假设它仅在值分别按升序/降序排列时才有效。
    • @SeanBrookins 。 . . min() 在这种情况下很方便,因为它有两个值。如果有更多的值,可以根据情况使用轻微的变化。
    【解决方案2】:

    返回数据:

     SELECT *
    FROM   t_hours t1
    WHERE  EXISTS (SELECT 1
                   FROM   t_hours t2
                   WHERE  t1.NAME = t2.NAME
                          AND t1.week = t2.week
                          AND t2.logged = 'N');  
    

    更新数据:

     UPDATE t_hours
    SET    logged = 'N'
    WHERE  EXISTS (SELECT 1
                   FROM   t_hours t2
                   WHERE  t1.NAME = t2.NAME
                          AND t1.week = t2.week
                          AND t2.logged = 'N');  
    

    如果数据集足够大,您可以按名称、周和记录类型进行分组。

    【讨论】:

    • 谢谢!这适用于我需要的东西!干净整洁,标记为已回答
    【解决方案3】:

    尝试如下-使用存在

    select t1.* from table_name t1
    where exists( select 1 from table_name t2 where t1.week=t2.week
                                              and t2.logged='N' and t1.name=t2.name
                 )
    

    【讨论】:

      【解决方案4】:

      这是你想要的吗?

         Update table set Logged='N' where
            Exists (Select 1 from(Select 
              Name,Workweek group by Name, 
             Workweek having count(Logged='N')
              >=1)t1 where Name=t1.name and  
               Workweek=t1.Workweek) 
      

      【讨论】:

      • 感谢您的评论,但我认为这在 SQL Server 中是不可接受的。 “姓名,工作周在”的 where 子句不起作用。我错过了什么吗?
      • 您遇到的错误是什么?如果这不起作用,请使用存在
      • 在 ',' 附近的上下文中指定的非布尔类型的表达式
      • Exists 返回了不错的结果,但再次感谢您的帮助!
      • 不,在 Where 子句中使用两个带有 IN 运算符的字段不起作用。但使用 EXISTS 确实有效。
      猜你喜欢
      • 1970-01-01
      • 2019-02-18
      • 1970-01-01
      • 1970-01-01
      • 2017-11-28
      • 1970-01-01
      • 2020-06-19
      • 2017-02-24
      • 1970-01-01
      相关资源
      最近更新 更多