在给定某些条件的情况下,无法编写查询以在每个“日期”中选择一行

时间:2009-08-06 08:18:28

标签: sql ms-access

在给定某些条件的情况下,我无法编写查询以在每个“日期”中选择一行。我的桌子有这样的结构:

ID  date       expiration    callput    iv     delta
1   1/1/2009   1/20/2009     C          0.4    0.61
2   1/1/2009   1/20/2009     C          0.3    0.51
3   1/1/2009   2/20/2009     C          0.2    0.41

我想写一个具有以下特征的查询:

  • 对于每一行,计算“天数”,即到期日期减去日期。例如,对于第一行,“天数”为19(1/20减去1/1)
  • 结果集只应包含“天”介于15到50之间的行
  • “callput”值必须为“C”
  • 对于每个日期,只显示一行。该行应具有以下特征:
    • delta应大于0.5
    • delta应该是大于0.5
    • 的最小数字
    • 如果有两行,则应选择具有较低天数的行

以上是上述示例数据的“天数”:

ID  date       expiration    days    callput    iv     delta
1   1/1/2009   1/20/2009     19      C          0.4    0.61
2   1/1/2009   1/20/2009     19      C          0.3    0.51
3   1/1/2009   2/20/2009     50      C          0.2    0.41

对于我的样本数据集,答案应该是第2行,因为第2行的“delta”高于0.5,第2行的delta为0.51,比第1行的0.61更接近0.5,第2行的“days”为19。排3的“天”50。

这是我到目前为止所写的查询:

SELECT date, Min(delta) AS MaxOfdelta, [expiration]-[date] AS days
FROM RAWDATA
WHERE (((delta)>0.5) AND ((callput)="C") AND (([expiration]-[date])>=15 And ([expiration]-[date])<=50))
GROUP BY date, [expiration]-[date]
ORDER BY date;

这有点工作,但有时,一个日期有多行,因为给定日期的两行可以有15到50之间的“天”。我无法让我的查询遵守规则“如果有是两行,应选择具有较低天数的行“。我还希望该行的“iv”值出现在我的查询结果集中。

我碰巧使用的是Microsoft Access,但任何SQL引擎的语法都会受到赞赏! : - )

2 个答案:

答案 0 :(得分:3)

您可以做的是在子查询中选择正确的行。此查询应该找到您要查找的行:

select [date], min([expiration]-[date])
from rawdata
where delta > 0.5
and callput = 'C' 
and [expiration]-[date] between 15 and 50
group by [date]

要查找属于这些行的增量,请将其放在子查询中并加入其中:

select *
from rawdata
inner join (
    select [date]
    ,      min([expiration]-[date]) as days
    from rawdata
    where delta > 0.5
    and callput = 'C' 
    and [expiration]-[date] between 15 and 50
    group by [date]
) as filter 
on filter.date = rawdata.date
and filter.days = rawdata.[expiration] - rawdata.[date]
where delta > 0.5
and callput = 'C' 

要搜索具有相同“天数”的行中的最低增量,您可以添加另一个子查询:

select
    SubDaysDelta.date
,   SubDaysDelta.MinDays
,   SubDaysDelta.MinDelta
,   min(rawdata.iv) as MinIv
from rawdata
inner join (
    select 
        SubDays.date
    ,   SubDays.MinDays
    ,   min(delta) as MinDelta
    from rawdata
    inner join (
        select [date]
        ,      min([expiration]-[date]) as MinDays
        from rawdata
        where delta > 0.5
        and callput = 'C' 
        and [expiration]-[date] between 15 and 50
        group by [date]
    ) as SubDays
    on SubDays.date = rawdata.date
    and SubDays.MinDays = rawdata.[expiration] - rawdata.[date]
    where delta > 0.5
    and callput = 'C' 
    group by SubDays.date, SubDays.MinDays
) as SubDaysDelta
on SubDaysDelta.date = rawdata.date
and SubDaysDelta.MinDays = rawdata.[expiration] - rawdata.[date]
and SubDaysDelta.MinDelta = rawdata.delta
where delta > 0.5
and callput = 'C' 
group by SubDaysDelta.date, SubDaysDelta.MinDays, SubDaysDelta.MinDelta

第一个子查询“SubDays”搜索具有最低“天数”的行。第二个子查询“SubDaysDelta”搜索“SubDays”集合中的最低增量。外部查询过滤剩余的所有重复项。

如果您使用视图,它将更具可读性和可维护性。第一个视图可以过滤掉callput和15-20“天”限制。这会让事情变得容易多了。

答案 1 :(得分:0)

VBA!

我希望我能像Andomar一样彻底,专注,乐于助人。我只能对他的回答完全投票。

然而......我想指出有可能有令人信服的理由转而使用VBA。即使您不熟悉VBA,控制和故障排除的好处也可能让您领先。而且我猜任何新的学习都会对你项目的其他部分有所帮助。

我希望我能像Andomar那样提供完整的答案。但是打个招呼吧。