SQL查询 - 比较行值

时间:2014-09-30 15:12:32

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

好的,这就是我的SQL DB中有两个表的问题。表1是一个简单的联系表,其中包含我的数据库中每个人的记录。表2是教育/考试表,其中DB中的每个人都有一条记录,但每条记录中都有多个测试。我正在尝试查询这两个表,以获取所有已过期值(比今天更早)的记录列表,以便我可以标记要删除的记录。存储在DB中的所有日期都是过期日期。关键在于,由于个人考试记录全部存在于记录的单行中,如果即使其中一个考试日期未到期,也需要保留整个记录。如果我有空值和过期日期的组合,我只能删除记录。不是每个人都有4条记录,大多数都有一两条记录,其余记录为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的记录,它们都是混合体。结果的片段如下所示:

| ID | FullName | ExamDate1 | ExamDatew | ExamDate3 | ExamDate4 |
| 10001 | John Doe 1/1/2008 |空|空| 2015年10月25日|
| 10002 | Jane Doe | 10/8/2020 | 2015年1月25日| 4/16/2014 |空|
| 10003 |约翰史密斯| 1/1/2010 | 6/5/2008 | 9/15/2013 | 7/8/2001 |
| 10004 |黛比苏| 8/14/2020 | 2016年6月5日|空|空|
| 10005 | Suzy Q | 5/9/2016 | 2014年4月15日| 4/9/2017 |无|

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

关于最简单的方法是什么?我在一个程序中考虑一个案例陈述,我在每个考试日期使用一个案例来浏览每个记录。有一个以空白开头的存储变量,并将该值作为变量+变量+'X'添加到该存储变量中,并在循环结束时查看变量的值。如果值为yyyy,则记录标记(显示),否则记录将保持不变。循环完成后,将变量重置为空白并重新开始。

我希望这是有意义的,因为它在我的头脑中,但并不总是在纸上。

感谢。

2 个答案:

答案 0 :(得分:0)

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))

答案 1 :(得分:0)

“好”家伙名单

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在名称和教育之间使用外键,甚至删除它们......