Проблема при написании запроса для выбора одной строки за «дату» при определенных условиях - PullRequest
1 голос
/ 06 августа 2009

У меня возникли проблемы при написании запроса для выбора одной строки за "дату" при определенных условиях. Моя таблица имеет такую ​​структуру:

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"
  • Для каждой даты показывать только одну строку. Этот ряд должен иметь следующие характеристики:
    • Дельта должна быть больше 0,5
    • Дельта должна быть наименьшим числом больше 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 выше 0,5, дельта строки 2 0,51 ближе к 0,5, чем 0,61 строки 1, а «дни» строки 2 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 ]

3 голосов
/ 06 августа 2009

Что вы можете сделать, это выбрать правильные строки в подзапросе. Этот запрос должен найти строки, которые вы ищете:

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 «дневным» ограничениям. Это сделало бы это намного проще.

0 голосов
/ 06 августа 2009

VBA!

Хотел бы я быть таким же тщательным, преданным и полезным слугой, как Андомар. Я могу только проголосовать за его ответ в полном восторге от него.

Однако ... Я хотел бы отметить, что, возможно, есть веские причины для перехода на VBA. Даже если вы новичок в VBA, преимущества в управлении и устранении неполадок могут вывести вас вперед. И я предполагаю, что любое новое обучение поможет в другом месте в вашем проекте.

Хотел бы я дать полный ответ, как это сделал Андомар. Но дайте ему удар.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...