具有多列的多个日期的SQL筛选

时间:2013-12-16 18:49:07

标签: sql sql-server

我正在尝试下拉由两个日期列过滤的记录 - 我需要显示所有“活动”记录。目前,我可以使用最新的“生效日期”来提取记录,但问题是我可能在多个生效日期之间有活动记录。

“有效”记录定义为生效日期等于或等于当前日期的记录(请参阅当前日期假设的注释),结束日期等于或大于当前日期。 “非活动”记录将是我示例中的第一行和第二行数据,活动记录将是第三行数据。

我正在处理与此类似的数据集:

+-------------+----------------+----------+---------+---------+---------+
|  Mode Name  | Effective Date | End Date | Mode ID | Param 1 | Param 2 |
+-------------+----------------+----------+---------+---------+---------+
| Single Mode |       20110102 | 20120313 |       1 | Green   | Metal   |
| Single Mode |       20120314 | 20131122 |       1 | Green   | Wood    |
| Single Mode |       20131123 | 29991231 |       1 | Orange  | Plastic |
| Multi Mode  |       20110102 | 20120313 |       5 | Orange  | Plastic |
| Multi Mode  |       20120314 | 20120501 |       5 | Red     | Metal   |
| Triple Mode |       20120314 | 20120314 |       3 | Blue    | Cloth   |
| Triple Mode |       20120315 | 20131122 |       3 | Red     | Wood    |
| Triple Mode |       20131123 | 20131130 |       3 | Red     | Wood    |
| Triple Mode |       20131201 | 29991231 |       3 | Orange  | Wood    |
| Double Mode |       20131123 | 29991231 |       2 | Green   | Metal   |
| Double Mode |       20131202 | 29991231 |       2 | Brown   | Plastic |
| Quad Mode   |       20131202 | 29991231 |       4 | Black   | Wood    |
| Quad Mode   |       20131203 | 29991231 |       4 | Green   | Plastic |
| Zero Mode   |       20090704 | 29991231 |       0 | Blue    | Cloth   |
+-------------+----------------+----------+---------+---------+---------+

我需要做的是查询,以便显示每个“活动”模式,但只显示“生效日期”列定义的最新活动模式。不应显示“结束”模式。 “结束”模式定义为在当前日期之前具有结束日期 - “29991231”被定义为“无结束日期”。理想情况下,上面的数据集会过滤到这个:

+-------------+----------------+----------+---------+---------+---------+
|  Mode Name  | Effective Date | End Date | Mode ID | Param 1 | Param 2 |
+-------------+----------------+----------+---------+---------+---------+
| Single Mode |       20131123 | 29991231 |       1 | Orange  | Plastic |
| Triple Mode |       20131201 | 29991231 |       3 | Orange  | Wood    |
| Double Mode |       20131202 | 29991231 |       2 | Brown   | Plastic |
| Quad Mode   |       20131203 | 29991231 |       4 | Green   | Plastic |
| Zero Mode   |       20090704 | 29991231 |       0 | Blue    | Cloth   |
+-------------+----------------+----------+---------+---------+---------+

一些注意事项:

  1. 假设此示例中的“当前日期”为2013-12-16。
  2. 您不能单独过滤结束日期 - 由于我们的系统工作方式,结束日期“29991231”不保证记录结束。例如,给定两个结尾日期为“29991231”的记录,具有较新生效日期的记录将取代具有较早生效日期的记录。
  3. 有些记录根本不会显示,因为它们在当前日期之前结束。
  4. 这是一个设计非常糟糕的旧系统。我相信有很多更好的存储数据的方法(相信我,我告诉你的不是最糟糕的部分) - 但不幸的是我坚持我拥有的东西。

2 个答案:

答案 0 :(得分:2)

你去吧

SELECT        
YourTable.ModeName, 
YourTable.EffectiveDate, 
YourTable.EndDate, 
YourTable.ModeId, 
YourTable.Param1, 
YourTable.Param2
FROM            
YourTable INNER JOIN 
(SELECT        
ModeName, 
MAX(EffectiveDate) AS MaximumEffectiveDate
FROM YourTable AS YourTable_1
WHERE (GETDATE() BETWEEN CONVERT(Date, EffectiveDate, 101) AND CONVERT(Date, EndDate, 101))
GROUP BY ModeName) AS GroupedByMode ON YourTable.ModeName = GroupedByMode.ModeName AND 
YourTable.EffectiveDate = GroupedByMode.MaximumEffectiveDate

只需将GETDATE()更改为您选择的日期

即可

希望这就是您所需要的,我复制您的数据并对其进行测试以获得相同的结果

enter image description here

答案 1 :(得分:1)

您可以使用CTE获取每个记录的单个记录:

with MaxDate as (select
       [Mode Name],
       max([Effective Date]) as mdate
       from
       table1
       group by [Mode Name])

   select
   *
   from
   table1 t1
   inner join
   MaxDate on mdate = [Effective Date]
   and t1.[Mode Name] = MaxDate.[Mode Name]
   where [End Date] = 29991231

SQL Fiddle