17.06.2008, 14:51 | #1 |
Модератор
|
Как подставить вычисляемое значение в Range у query
Задача сделать выпадающий список с таблицы рабочих смен.
Если смена открыта 17.06.2008 с 8:00 до 20:00 в сейчас время к примеру 14 часов.. то запрос выполнится. А как быть если смена открыта 17.06.2008 23 часа до 18.06.2008 до 6 утра. а сейчас время 2:00 утра, то запрос не выполнится. Условие надо поправить так чтоб время открытой смены проверялось между двумя датами queryBuildDataSource.addRange(fieldnum(MilkShifts,StartTime)).value("<"+t); queryBuildDataSource.addRange(fieldnum(MilkShifts,EndTime)).value(">" + t); Как это сделать? Что т оне соображу. X++: static void lookupIDShift(FormStringControl _ctrl) { Query query=new Query(); QueryBuildDataSource queryBuildDataSource; QueryBuildRange queryBuildRange; QueryRun qr; //Таблицы SysCompanyUserInfo scUI; MilkGroupMaterialResponsibilityLine mGMRLine; SysTableLookup sysTableLookup = SysTableLookup::newParameters(tableNum(MilkShifts), _ctrl); Str t= time2str(timenow(),1,1), d=strfmt("%1", systemdateget()), IDgmt, saveText; Str 300 war, warNull; ; war="Вы не определены ни в одну группу материальной ответственности поэтому не можете создавать складские и производстенные журналы."+ " Обратитесь к администратору системы или используйте форму [Управление запасами/ Настройка/ Смены/ Группы материальной ответственности]"; warNull="Ни одна смена для групп материальной ответственности, в которой Вы входите, не является открытой на текущий момент."+ " Отредактируйте Группы материальной ответственности или используйте периодическую операцию Закрытие смены"; saveText = _ctrl.text(); _ctrl.text(""); // Disable filter effects sysTableLookup.addLookupfield(fieldNum(MilkShifts,IDShift)); sysTableLookup.addLookupfield(fieldNum(MilkShifts,StartTime)); sysTableLookup.addLookupfield(fieldNum(MilkShifts,EndTime)); sysTableLookup.addLookupfield(fieldNum(MilkShifts,StartDate)); sysTableLookup.addLookupfield(fieldNum(MilkShifts,EndDate)); sysTableLookup.addLookupfield(fieldNum(MilkShifts,Milk_IDGroupMaterialResponsibility)); queryBuildDataSource=query.addDataSource(tablenum(MilkShifts)); //Ищем сотрудника по пользовательским связям через текущего пользователя SELECT firstonly EmplId FROM scUI where scUI.UserId==curUserId(); //Ищем ID группы материальной ответственности while select IDGroupMaterialResponsibility from mGMRLine where mGMRLine.EmplId==scUI.EmplId { IDgmt+=mGMRLine.IDGroupMaterialResponsibility+","; } IDgmt=substr(IDgmt,1,strlen(IDgmt)-1); if (IDgmt=="") Box::warning( war, "Вы не состоите ни в одной группе материальной ответственности" ); else { // Запрос возвращает номер текущих смен. Надо сравнить с тем есть ли у этой смены ИД группы мат отв. queryBuildDataSource.addRange(fieldnum(MilkShifts,StartTime)).value("<"+t); queryBuildDataSource.addRange(fieldnum(MilkShifts,EndTime)).value(">" + t); queryBuildDataSource.addRange(fieldnum(MilkShifts,StartDate)).value(".." + d ); queryBuildDataSource.addRange(fieldnum(MilkShifts,EndDate)).value(d + ".."); queryBuildDataSource.addRange(fieldnum(MilkShifts,StatusShift)).value(enum2str(StatusShift::Open)); queryBuildDataSource.addRange(fieldnum(MilkShifts,Milk_IDGroupMaterialResponsibility)).value(IDgmt);// Список групп в которых учавствует пользователь qr= new QueryRun(query); If(qr.next()) { // sysTableLookup.parmTmpBuffer(MilkShifts); sysTableLookup.parmQuery(query); sysTableLookup.performFormLookup(); } else Box::warning( warNull, "Необходимо открыть смену" ); } _ctrl.text(saveText); } SELECT * FROM MilkShifts WHERE ((StartTime<53103)) AND ((EndTime>53103)) AND ((StartDate<={ts '2008-06-17 00:00:00.000'})) AND ((EndDate>={ts '2008-06-17 00:00:00.000'})) AND ((StatusShift = 0)) AND ((Milk_IdGroupmaterialResponsibility = N'Гр2')) |
|
17.06.2008, 14:59 | #2 |
Боец
|
Вычисляемые поля аксапта не поддерживает
EDIT: пардон., не понял вопроса сразу... Чтобы поставить условие на интервал нужно использовать метод SysQuery::range(anytype _from, anytype _to) , т.е. X++: ...addRange(fieldnum(MilkShifts,StartDate)).value(SysQuery::range(date1, date2)); Последний раз редактировалось DSPIC; 17.06.2008 в 15:07. |
|
17.06.2008, 15:18 | #3 |
Участник
|
Перейти на 5.0 - там UTCdatetime используется.
А если по теме - то видимо надо писать сложный фильтр такого плана: (тек.время > время начала смены И тек.дата = дата начала смены) ИЛИ (тек.время < время конца смены И тек.дата = дата конца смены) ИЛИ (тек.дата > дата начала смены И тек.дата < дата конца смены) (это если смена больше суток) |
|
17.06.2008, 15:30 | #4 |
Модератор
|
DSPIC
про использования интервала для даты это можно, но что делать со временем не понятно. Поля StrartTime и EndTime определены как TimeHour24 или можно сними работать как с целыми числами (каждая единица секунда) 7200 =2ч если StartTime =23:00: а EndTime = 6:00:00 а t = 2:00:00 то условие StartTime<t AND t< EndTime теряет всякий смысл. 23 > 2 Надо как кто привязать дату ко времени. Если сделать так X++: queryBuildDataSource.addRange(fieldnum(MilkShifts,StartTime)).value("<" + t +"-( StartDate -"+ d+" )*86400" ); //86400 - это сутки в секундах (mShifts.StartTime<(t+(d-mShifts.StartDate)*86400) && (t-(mShifts.EndDate-d)*86400)<mShifts.EndTime t - текущее время d - текущая дата Если текущая дата = StartDate и EndDate то выражение (mShifts.EndDate-d)*86400) == 0 А если время начальное и конечное в разных датах то данное выражение имеет мысл. Но как его завернуть в query ? |
|
17.06.2008, 15:32 | #5 |
Модератор
|
kashperuk
Если бы можно было бы использовать ИЛИ в query. Там только AND. |
|
17.06.2008, 16:48 | #7 |
Модератор
|
Добавил условие
X++: sQuery=strfmt("(StartTime < (%1 + (StartDate - %2 )*86400)) AND ((%3 - (EndDate - %4 )*86400)< EndTime)",timenow(),date2num(systemdateget()),timenow(),date2num(systemdateget())); queryBuildDataSource.addRange(fieldnum(MilkShifts,recId)).value(squery); SELECT * FROM MilkShifts WHERE (((StartTime < (60419 + (StartDate - 39614 )*86400)) AND ((60419 - (EndDate - 39614 )*86400)< EndTime))) AND ((StartDate<={ts '2008-06-17 00:00:00.000'})) AND ((EndDate>={ts '2008-06-17 00:00:00.000'})) AND ((StatusShift = 0)) AND ((Milk_IdGroupmaterialResponsibility = N'Гр2' OR Milk_IdGroupmaterialResponsibility = N'Гр3')) Выдает: Ошибка: Невозможно выбрать запись в Смены (MilkShifts). База данных SQL обнаружила ошибку. Где ошибка? не подскажете? Последний раз редактировалось Poleax; 17.06.2008 в 16:55. |
|
17.06.2008, 16:56 | #8 |
Участник
|
Почитайте вот это
http://www.axaptapedia.com/Expressions_in_query_ranges Возможно, попробуйте поставить еще одни скопки вокруг всего выражения. Но я, честно говоря, не помню, чтобы даже через расширенный фильтр оно позволяло вычисления вставлять в запрос. Пишите лучше так, как я показал выше. |
|
|
За это сообщение автора поблагодарили: jeky (2). |
17.06.2008, 17:13 | #9 |
Модератор
|
Цитата:
Сообщение от kashperuk
Перейти на 5.0 - там UTCdatetime используется.
А если по теме - то видимо надо писать сложный фильтр такого плана: (тек.время > время начала смены И тек.дата = дата начала смены) ИЛИ (тек.время < время конца смены И тек.дата = дата конца смены) ИЛИ (тек.дата > дата начала смены И тек.дата < дата конца смены) (это если смена больше суток) SELECT * FROM MilkShifts WHERE (((StartTime < (60419 + (StartDate - 39614 )*86400)) AND ((60419 - (EndDate - 39614 )*86400)< EndTime))) AND ((StartDate<={ts '2008-06-17 00:00:00.000'})) AND ((EndDate>={ts '2008-06-17 00:00:00.000'})) AND ((StatusShift = 0)) AND ((Milk_IdGroupmaterialResponsibility = N'Гр2' OR Milk_IdGroupmaterialResponsibility = N'Гр3')) осталось разобраться с приведением типов. На счет запроса (тек.время > время начала смены И тек.дата = дата начала смены) ИЛИ (тек.время < время конца смены И тек.дата = дата конца смены) ИЛИ (тек.дата > дата начала смены И тек.дата < дата конца смены) (это если смена больше суток) Тек. время преобразовать в целое число? тек. дату тоже в целое? или оставить так как strfmt делает ? ('18:10:10' и 17.06.2008) |
|
17.06.2008, 17:24 | #10 |
Модератор
|
Изменил условие запроса как советовал kashperuk
sQuery=strfmt("((%1>StartTime AND %2=StartDate) OR ( %1<EndTime AND %2=EndTime) OR (%2>StartDate AND %2<EndDate))",timenow(),date2num(systemdateget())); queryBuildDataSource.addRange(fieldnum(MilkShifts,recId)).value(squery); SELECT * FROM MilkShifts WHERE ((((62459>StartTime AND 39614=StartDate) OR ( 62459<EndTime AND 39614=EndTime) OR (39614>StartDate AND 39614<EndDate)))) AND ((StatusShift = 0)) AND ((Milk_IdGroupmaterialResponsibility = N'Гр2' OR Milk_IdGroupmaterialResponsibility = N'Гр3')) Появляется ошибка: Ошибка расширенного диапазона запроса: Ожидается правая круглая скобка рядом с 23. |
|
17.06.2008, 17:33 | #11 |
----------------
|
совет
1. каждое условие в свою пару скобок (((усл1) AND (усл2)) OR ((усл3) AND (усл4)))
2. вместо date2num использовать date2xppstr Интересно, есть ли люди которые могут написать подобное условие с первого раза без ошибок... |
|
17.06.2008, 17:34 | #12 |
Участник
|
Не почитал видимо внимательно ту статью, что я ссылку дал.
В запросе этом надо использовать X++ синтаксис, то есть (((%1 > StartTime) && (%2 == StartDate) || ().... Время преобразуй в число А дату функцией date2StrXpp |
|
|
За это сообщение автора поблагодарили: Poleax (1). |
17.06.2008, 17:45 | #13 |
Модератор
|
sQuery=strfmt("(((%1>StartTime) && (%2==StartDate)) || ((%1<EndTime) && (%2==EndTime)) || ((%2>StartDate) && (%2<EndDate)))",timenow(),d);
SELECT * FROM MilkShifts WHERE (((((63797>StartTime) && (17.06.2008==StartDate)) || ((63797<EndTime) && (17.06.2008==EndTime)) || ((17.06.2008>StartDate) && (17.06.2008<EndDate))))) AND ((StatusShift = 0)) AND ((Milk_IdGroupmaterialResponsibility = N'Гр2' OR Milk_IdGroupmaterialResponsibility = N'Гр3')) Ошибка таже самая Ошибка расширенного диапазона запроса: Ожидается правая круглая скобка рядом с 32. |
|
17.06.2008, 17:48 | #14 |
Участник
|
Дату неправильно преобразовал. Смотри советы выше про использование date2StrXpp
|
|
17.06.2008, 17:48 | #15 |
Модератор
|
kashperuk
как я понима от всех дополнительных queryBuildDataSource.addRange(fieldnum(MilkShifts,StatusShift)).value(enum2str(StatusShift::Open)); надо избавляться и весь Where собирать в strfmt ? чтоб небыло различий между AND и && в одной строке |
|
17.06.2008, 17:58 | #16 |
Участник
|
Нет, не нужно избавляться от оставшихся. Ахапта сама раздуплит и те, и те
Они умная (иногда) |
|
17.06.2008, 18:52 | #17 |
Модератор
|
kashperuk
Спасибо огромное, заработало. и за date2StrXpp спасибо. |
|
Теги |
документация, ax2009 |
|
|