-
СУБД Oracle, в БД имеется таблица, в которой одно из полей дата и время, второе сумма операции, третье входящий остаток.
Возможно ли одним запросом получить список входящих остатков на начало каждой из дат, т.е. в одном дне несколько записей имеющих разное время, соответственно остаок на начало имеет наименьшее время.
на выходе нужен список из пар: дата и время, входящий остаток.
-
Возможно, с использованием аналитических функций.
-
Или я что-то не понял или без аналитики где-то так: WITH foo AS (
SELECT TO_DATE('01.01.2000 01:00','dd.mm.yyyy hh24:mi') your_date, 1 rem FROM dual
UNION ALL
SELECT TO_DATE('01.01.2000 02:00','dd.mm.yyyy hh24:mi') your_date, 2 rem FROM dual
UNION ALL
SELECT TO_DATE('02.01.2000 01:00','dd.mm.yyyy hh24:mi') your_date, 4 rem FROM dual
UNION ALL
SELECT TO_DATE('02.01.2000 02:00','dd.mm.yyyy hh24:mi') your_date, 6 rem FROM dual
)
SELECT TRUNC(your_date), MIN(rem) FROM foo
GROUP BY TRUNC(your_date);
-
> [2] Игорь Шевченко © (24.11.10 20:36) > SELECT TRUNC(your_date), MIN(rem) FROM foo > GROUP BY TRUNC(your_date);
Наверно как-то так надо, потому что MIN(rem) вряд ли правильно
SELECT your_date, rem
FROM tbl t LEFT JOIN (
SELECT MIN(your_date)
FROM tbl
GROUP BY TRUNC(your_date)
) tm ON t.your_date = tm.your_date
;
-
> потому что MIN(rem) вряд ли правильно
Значит через аналитику. WITH foo AS (
SELECT TO_DATE('01.01.2000 01:00','dd.mm.yyyy hh24:mi') your_date, 2 rem FROM dual
UNION ALL
SELECT TO_DATE('01.01.2000 02:00','dd.mm.yyyy hh24:mi') your_date, 1 rem FROM dual
UNION ALL
SELECT TO_DATE('02.01.2000 00:30','dd.mm.yyyy hh24:mi') your_date, 4 rem FROM dual
UNION ALL
SELECT TO_DATE('02.01.2000 02:00','dd.mm.yyyy hh24:mi') your_date, 6 rem FROM dual
)
SELECT your_date,rem FROM foo
WHERE your_date IN (SELECT DISTINCT MIN(your_date) OVER (PARTITION BY TRUNC(your_date)) FROM foo) Вылезает 01.01.2000 01:00, 2 02.01.2000 00:30, 4
-
>Получение остатков на каждую дату
WITH foo AS (
SELECT TO_DATE('01.01.2000 01:00','dd.mm.yyyy hh24:mi') your_date, 2 rem FROM dual
UNION ALL
SELECT TO_DATE('01.01.2000 02:00','dd.mm.yyyy hh24:mi') your_date, 1 rem FROM dual
UNION ALL
SELECT TO_DATE('02.01.2000 00:30','dd.mm.yyyy hh24:mi') your_date, 4 rem FROM dual
UNION ALL
SELECT TO_DATE('02.01.2000 02:00','dd.mm.yyyy hh24:mi') your_date, 6 rem FROM dual
)
SELECT trunc(g.your_date),
min(g.rem ) keep (dense_rank first order by g.your_date)
FROM foo g
GROUP BY trunc(g.your_date)
-
>Inovet © (24.11.10 22:18) [3]если нужно на КАЖДУЮ строку, то двойной FTS - самый последний вариант и можно делать так, как предлагал Игорь Шевченко - через аналитику:
WITH foo AS (
SELECT TO_DATE('01.01.2000 01:00','dd.mm.yyyy hh24:mi') your_date, 2 rem FROM dual
UNION ALL
SELECT TO_DATE('01.01.2000 02:00','dd.mm.yyyy hh24:mi') your_date, 1 rem FROM dual
UNION ALL
SELECT TO_DATE('02.01.2000 00:30','dd.mm.yyyy hh24:mi') your_date, 4 rem FROM dual
UNION ALL
SELECT TO_DATE('02.01.2000 02:00','dd.mm.yyyy hh24:mi') your_date, 6 rem FROM dual
)
SELECT g.your_date, g.rem,
first_value(g.rem) over(partition by trunc(g.your_date) order by g.your_date)
FROM foo g
order by g.your_date
-
> [6] Кщд (25.11.10 11:16) > если нужно на КАЖДУЮ строку, то двойной FTS - самый последний > вариант и можно делать так, как предлагал Игорь Шевченко > - через аналитику:
Я особенносте Оракл не знаю, поэтому и написал "как-то так".
-
Всем спасибо, попробую предложенные варианты. После того как запостил вопрос написал свое решение, оно почему-то очень громоздкое: Select SS.CID, SS.DayList,
(Select Abs(C_4)
From IBS.VW_CRIT_FULL_RECORDS
Where Collection_Id = SS.CID And
C_1 = TO_DATE(SS.MinTime, 'DD/MM/YYYY HH24:MI:SS') And
RowNum <= 1) Ostatok
From
(Select Days.CID, Days.DayList,
(Select To_Char(Min(C_1), 'DD/MM/YYYY HH24:MI:SS')
From IBS.VW_CRIT_FULL_RECORDS
Where (Collection_Id = Days.CID) And
(C_1 >= TO_DATE(Days.DayList || ' 00:00:00', 'DD/MM/YYYY HH24:MI:SS')) And
(C_1 <= TO_DATE(Days.DayList || ' 23:59:59', 'DD/MM/YYYY HH24:MI:SS'))
) MinTime
From
(Select Distinct CID, DL.DayList
From
(Select Collection_Id CID, TO_CHAR(C_1, 'DD/MM/YYYY') DayList
From IBS.VW_CRIT_FULL_RECORDS
Where (Collection_Id = '4290840243') And
(C_1 >= TO_DATE('06/01/2010 00:00:00', 'DD/MM/YYYY HH24:MI:SS')) And
(C_1 <= TO_DATE('24/11/2010 23:59:59', 'DD/MM/YYYY HH24:MI:SS'))
) DL
) Days
) SS
в данной части на клиенте будут подставлены нужные значения Where (Collection_Id = '4290840243') And
(C_1 >= TO_DATE('06/01/2010 00:00:00', 'DD/MM/YYYY HH24:MI:SS')) And
(C_1 <= TO_DATE('24/11/2010 23:59:59', 'DD/MM/YYYY HH24:MI:SS'))
-
>xmen (25.11.10 17:17) [8] 1. трижды обращаетесь к одной и той же таблице; 2. неаккуратно используете псевдонимы; 3. лишние преобразования date-char-date - несмотря на то, что Вам в этой ветке рассказали о trunc 4. с какой целью использован rownum?
было бы отлично, если бы привели пример исходных данных(напр., Игорь Шевченко © (24.11.10 20:36) [2]) и тех, что нужно получить.
-
>Inovet © (25.11.10 16:09) [7] тот вариант, что предложили Вы, не просто не вернет нужного результата(т.е. это аналог select your_date, rem from tbl:)), но даже не будет выполняться не только на Oracle
-
> >xmen (25.11.10 17:17) [8]1. трижды обращаетесь к одной > и той же таблице;2. неаккуратно используете псевдонимы;3. > лишние преобразования date-char-date - несмотря на то, > что Вам в этой ветке рассказали о trunc4. с какой целью > использован rownum?было бы отлично, если бы привели пример > исходных данных(напр., Игорь Шевченко © (24.11.10 20:36) > [2]) и тех, что нужно получить.
Действительно трижды - так уж получилось :-) неаккуратно - поясните. что trunc используют видел, но во-первых я был не в курсе, что она делает, а во вторых написал свой "шедевр" немного раньше чем ответили на форуме.
Исходные данные такие:
Дата и время проводки Входящий остаток 08.05.2010 08:39:16 -842783,49 08.05.2010 08:39:16 -843337,66 08.05.2010 23:59:59 -843483,49 08.05.2010 23:59:59 -878531,31 08.05.2010 23:59:59 -880921,31 08.05.2010 23:59:59 -884204,83 08.05.2010 23:59:59 -885710,53 08.05.2010 23:59:59 -886010,53 08.05.2010 23:59:59 -888010,53 08.05.2010 23:59:59 -889010,53 08.05.2010 23:59:59 -890010,53 08.05.2010 23:59:59 -985010,53 08.05.2010 23:59:59 -1032020,53 08.05.2010 23:59:59 -1041030,53 08.05.2010 23:59:59 -3343644,68 08.05.2010 23:59:59 -3251024,68 08.05.2010 23:59:59 -3231224,68 08.05.2010 23:59:59 -3118431,91 08.05.2010 23:59:59 -3118481,91 08.05.2010 23:59:59 -3118531,91 08.05.2010 23:59:59 -3118536,49 08.05.2010 23:59:59 -3118561,91 08.05.2010 23:59:59 -3118611,91 08.05.2010 23:59:59 -3118677,58 08.05.2010 23:59:59 -3118727,58 08.05.2010 23:59:59 -3118777,58 08.05.2010 23:59:59 -3118927,58 08.05.2010 23:59:59 -3119077,58 08.05.2010 23:59:59 -3119227,58 08.05.2010 23:59:59 -3121227,58 08.05.2010 23:59:59 -3123227,58 08.05.2010 23:59:59 -3121727,58 08.05.2010 23:59:59 -3120227,58 08.05.2010 23:59:59 -3119227,58 08.05.2010 23:59:59 -3116227,58 08.05.2010 23:59:59 -3113227,58 08.05.2010 23:59:59 -3110222,58 08.05.2010 23:59:59 -3107534,58 08.05.2010 23:59:59 -3105534,58 08.05.2010 23:59:59 -3106034,58 08.05.2010 23:59:59 -3105874,58 08.05.2010 23:59:59 -3103874,58 08.05.2010 23:59:59 -3096874,58 08.05.2010 23:59:59 -3293124,58 08.05.2010 23:59:59 -1293124,58
В итоге нужно получить 08.05.2010 -842783,49 Естественно в исходных данных дней гораздо больше.
Изначально, в качестве примера мне показывали другие данные, где у каждой операции было свое время, но впоследствии оказалось, что операции могут быть проведены пакетно и тогда у них будет одно время, поэтому было добавлено rownum
-
решение из [2] никак ? заменив MIN на MAX Насколько я вижу, у тебя остаток все время уменьшается в течение одной даты.
-
> [10] Кщд (26.11.10 08:03) > [10] Кщд (26.11.10 08:03) > тот вариант, что предложили Вы, не просто не вернет нужного > результата(т.е. это аналог select your_date, rem from tbl: > )), но даже не будет выполняться не только на Oracle
Да. Вот так должен работать
SELECT t.your_date, t.rem
FROM tbl t JOIN (
SELECT MIN(your_date) as your_date
FROM tbl
GROUP BY TRUNC(your_date)
) tm ON t.your_date = tm.your_date
Судя по данным в > [11] xmen (26.11.10 10:22)
условие > [0] xmen (24.11.10 19:44) > соответственно остаок на начало имеет наименьшее время
невыполнимо, нет уникального признака, какая проводка была первой. Где здесь наименьшее время? > 08.05.2010 08:39:16 -842783,49 > 08.05.2010 08:39:16 -843337,66
-
>xmen (26.11.10 10:22) [11] >неаккуратно - поясните. нет псевдонимов у таблиц и полей - это чревато непредсказуемым результатом запроса
по поводу rownum: т.е. Вам всё равно какой из двух остатков с одним и тем же временем брать?) пора бы задуматься об уникальном идентификаторе записи или - как минимум - сменить тип поля на timestamp
>Дата и время проводки Входящий остаток >08.05.2010 08:39:16 -842783,49
с такими данными неудобно работать >было бы отлично, если бы привели пример исходных данных(напр., >Игорь Шевченко © (24.11.10 20:36) [2]) и тех, что нужно получить.
-
>Inovet © (26.11.10 20:41) [13]
>невыполнимо, нет уникального признака, какая проводка была первой. >Где здесь наименьшее время? абсолютно в точку) в этом случае автор берет любой остаток - какой заблагорассудится, чтобы пользователям учетной системы было не скучно т.е. теоретически дважды выполненный запрос вернет разные результаты на одних и тех же данных)
-
> >xmen (26.11.10 10:22) [11]>неаккуратно - поясните.нет > псевдонимов у таблиц и полей - это чревато непредсказуемым > результатом запроса
что именно мне нужно ставить и где, чтобы такого не произошло? по поводу rownum: т.е. Вам всё равно какой из двух остатков с одним и тем же временем брать?)пора бы задуматься об уникальном идентификаторе записи или - как минимум - сменить тип поля на timestamp Мне не все равно, но другого варианта я не вижу. Скорее всего у записи есть уникальный идентификатор, но мне эта информация не доступна. Я не разработчки данной системы, но ведь ни кто мне запрещает мне использовать свои запросы ... > решение из [2] никак ? заменив MIN на MAXНасколько я вижу, > у тебя остаток все время уменьшается в течение одной даты. >
В приведенных данных остаток действительно все время уменьшается, но в жизни могут быть и другие ситуации, в общем-то один из предложенных здесь вариантов решения меня вполне устраивает. Так что все огромное спасибо. > Кщд (29.11.10 08:51) [15] > >Inovet © (26.11.10 20:41) [13]>невыполнимо, нет уникального > признака, какая проводка была первой. >Где здесь наименьшее > время?абсолютно в точку)в этом случае автор берет любой > остаток - какой заблагорассудится, чтобы пользователям учетной > системы было не скучнот.е. теоретически дважды выполненный > запрос вернет разные результаты на одних и тех же данных)
Все верно, я беру любую, но это не критично, суть в том, что такую работу нужно делать либо вручную, либо как-то ее автоматизировать, был выбран именно второй вариант, в итоге есть база на акссессе, которая через vba и ado цепляется к oracle, выполняет запрос, забирает данные, далее они другим запросом сравниваются с контрольными значениями, результаты отклонений анализируется сотрудником, берутся объяснения, наказываются люди - последняя часть стандартна :-)
-
>xmen (29.11.10 11:28) [16] >что именно мне нужно ставить и где, чтобы такого не произошло? псевдонимы(alias) таблиц(обязательно) и полей(желательно).
>Мне не все равно, но другого варианта я не вижу. Вы понимаете, что дважды выполнив Ваш запрос за 08.05.2010, Вы можете получить РАЗНЫЕ суммы остатка?
>Все верно, я беру любую, но это не критично если для Вас это некритично, то можно просто воспользоваться ф-цией random для получения остатка на дату)
-
> >xmen (29.11.10 11:28) [16]>что именно мне нужно ставить > и где, чтобы такого не произошло?псевдонимы(alias) таблиц(обязательно) > и полей(желательно).
ммм, пример можно?
> >Мне не все равно, но другого варианта я не вижу. Вы понимаете, > что дважды выполнив Ваш запрос за 08.05.2010, Вы можете > получить РАЗНЫЕ суммы остатка?
вы понимаешь, что если у вас в кармане 10 000, а машина стоит 1 000 000, то будь у вас хоть 9 000, хоть 11 000, вы все равно не сможете ее купить. Там ситуация такова, что если нужное мне превышение будет, то оно будет на сотни тысяч и это все равно вылезет. Это как превышение скорости до 10 км/ч не является нарушением :-) Если вы знаете другой вариант решения, то выкладывайте, буду рад услышать, применить.
> >Мне не все равно, но другого варианта я не вижу. Вы понимаете, > что дважды выполнив Ваш запрос за 08.05.2010, Вы можете > получить РАЗНЫЕ суммы остатка?
Понимаю, поэтому буду выполнять 1 раз :-) Не кретично, ни кто не разобравшись шашкой махать не будет, так что любой из сотрудников всегда сможет доказать свою правоту.
> >Все верно, я беру любую, но это не критичноесли для Вас > это некритично, то можно просто воспользоваться ф-цией random > для получения остатка на дату)
я подумаю :-)
-
>xmen (29.11.10 12:43) [18] >ммм, пример можно? google: sql table alias
>Если вы знаете другой вариант решения, то выкладывайте, буду рад >услышать, применить.
>Кщд (29.11.10 08:46) [14] >пора бы задуматься об уникальном идентификаторе записи или - как >минимум - сменить тип поля на timestamp в конце концов, если добавить/сменить тип поля в исходной таблице нет возможности, повесить триггер, котором писать сумму остатка с уникальным идентификатором в свою таблицу
>Понимаю, поэтому буду выполнять 1 раз и получать случайное значение из таблицы бессмысленная работа
|