【问题标题】:SQL Query - compare row valuesSQL 查询 - 比较行值
【发布时间】:2014-09-30 15:12:32
【问题描述】:

好的,问题是我的 SQL DB 中有两个表。表 1 是一个简单的联系人表,其中包含我数据库中每个人的记录。表 2 是一个教育/考试表,其中数据库中的每个人都有一条记录,但每条记录中都有多个测试。我正在尝试查询这两个表以获取具有过期值(早于今天)的所有记录的列表,以便我可以将记录标记为删除。数据库中存储的所有日期都是过期日期。更重要的是,由于个人考试记录都存在于记录的单行中,因此即使有一个考试日期未过期,则需要保留整个记录。如果我有空值和过期日期的组合,我只能删除一条记录。不是每个人都有 4 条记录,大多数有 1 或 2 条,其余记录为 Null。所以这是我获取数据的代码:

select n.id, n.FULL_NAME, e.ExamDate1, e.ExamDate2, e.ExamDate3, e.ExamDate4
from Name n inner join Education e on n.id = e.id

这让我获得了 57k 条记录,它们都是混合的。结果的 sn-p 如下所示:

|身份证 |全名 |考试日期1 |考试日期 |考试日期3 |考试日期4 |
| 10001 |约翰·多伊 | 2008 年 1 月 1 日 |空 |空 | 2015 年 10 月 25 日 |
| 10002 |简·多伊 | 2020 年 10 月 8 日 | 2015 年 1 月 25 日 | 2014 年 4 月 16 日 |空|
| 10003 |约翰·史密斯 | 2010 年 1 月 1 日 | 2008 年 6 月 5 日 | 2013 年 9 月 15 日 | 2001 年 7 月 8 日 |
| 10004 |黛比苏 | 2020 年 8 月 14 日 | 2016 年 6 月 5 日 |空 |空|
| 10005 |苏茜 Q | 2016 年 5 月 9 日 | 2014 年 4 月 15 日 | 2017 年 4 月 9 日 |空|

我需要能够获取这些数据并对其进行分类,并标记每个人的好坏。如果至少有一个列出的日期未过期,则为好;如果所有列出的日期已过期或所有日期均已过期并且没有日期的记录为空,则为不好。

您对最简单的方法有什么想法吗?我正在考虑一个程序中的案例陈述,在该程序中,我使用每个考试日期的案例来遍历每条记录。有一个以空白开头的存储变量,并为该存储变量添加一个值,变量 = 变量 + 'X',在循环结束时,查看变量的值。如果该值为 yyyy,则记录被标记(显示),如果不是,则该记录被单独保留。循环完成后,将变量重置为空白并重新开始。

我希望这在我的脑海中是有意义的,但并不总是在纸面上。

谢谢。

【问题讨论】:

    标签: sql stored-procedures sql-server-2012 multi-table


    【解决方案1】:

    Sql 是一种基于集合的语言。语言本身不是标记好坏,而是返回一个特定的集合。在这种情况下,您可能需要一组过期记录。您拥有面前的所有信息,因此不需要案例陈述或循环浏览数据。一般情况下,尽量不要循环遍历sql中的数据。

    因此,您需要的是符合以下条件的所有人员的列表:考试日期 1 为空或已过期,考试 2 为空或已过期,考试 3 为空或已过期,考试 4 为空或已过期。这些条件很好地转化为 sql。

    select n.id, n.FULL_NAME, e.ExamDate1, e.ExamDate2, e.ExamDate3, e.ExamDate4
    from Name n inner join Education e on n.id = e.id
    where (e.ExamDate1 is null or e.ExamDate1 < cast(getDate() as date))
    and (e.ExamDate2 is null or e.ExamDate2 < cast(getDate() as date))
    and (e.ExamDate3 is null or e.ExamDate3 < cast(getDate() as date))
    and (e.ExamDate4 is null or e.ExamDate4 < cast(getDate() as date))
    

    【讨论】:

    • 好的,这看起来不错,但这会考虑好/坏的任何组合吗?仅仅因为有一个考试日期,并不意味着有一个考试日期。因此,一个人在 Exam1 和 Exam3 中只能有一个日期,而在 Exam2 中只有一个日期,但 Exam1 已过期,而 Exam3 没有,请原谅这里的任何愚蠢行为,但不是“和”命令从左到右看,但不会跳来跳去或确实这让它可以跳来跳去查看所有记录并相应地报告?这是我需要任何可能的好/坏组合的地方。
    • 并且意味着语句需要评估为真。 True 和 false 的计算结果为 false。这一切都基于布尔逻辑。因此,第一部分说examDate1 必须为null 或小于今天的日期。如果这是真的,我们看下一部分。如果 ExamDate2 大于今天,则评估停止并且不返回记录。
    • 太棒了。谢谢。我想我想太多了,甚至没有为此关联一个简单的和声明。这看起来就像我需要它一样工作。
    【解决方案2】:

    “好”人名单

    select n.id, n.FULL_NAME, e.ExamDate1, e.ExamDate2, e.ExamDate3, e.ExamDate4
    from Name n inner join Education e on n.id = e.id
    where
      (
        ISNULL(e.ExamDate1,'19000101') >= GETDATE()
        or
        ISNULL(e.ExamDate2,'19000101') >= GETDATE()
        or
        ISNULL(e.ExamDate3,'19000101') >= GETDATE()
        or
        ISNULL(e.ExamDate4,'19000101') >= GETDATE()
        or
      )
    

    标记坏人(仅在名称表中)

    update n
    set n.YOUR_FLAG_COLUMN = 'Y'
    from Name n inner join Education e on n.id = e.id
    where
      (
        ISNULL(e.ExamDate1,'19000101') < GETDATE()
        and
        ISNULL(e.ExamDate2,'19000101') < GETDATE()
        and
        ISNULL(e.ExamDate3,'19000101') < GETDATE()
        and
        ISNULL(e.ExamDate4,'19000101') < GETDATE()        
      )
    

    或者,如果您在名称和教育之间使用 ON CASCADE DELETE 甚至删除它们...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多