![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Получение остатков на каждую дату
xmen © (2010-11-24 19:44:00)СУБД Oracle, в БД имеется таблица, в которой одно из полей дата и время, второе сумма операции, третье входящий остаток.
Возможно ли одним запросом получить список входящих остатков на начало каждой из дат, т.е. в одном дне несколько записей имеющих разное время, соответственно остаок на начало имеет наименьшее время.
на выходе нужен список из пар: дата и время, входящий остаток.
Кщд (2010-11-29 08:46:00) [21]>xmen (26.11.10 10:22) [11]
>неаккуратно - поясните.
нет псевдонимов у таблиц и полей - это чревато непредсказуемым результатом запроса
по поводу rownum: т.е. Вам всё равно какой из двух остатков с одним и тем же временем брать?)
пора бы задуматься об уникальном идентификаторе записи или - как минимум - сменить тип поля на timestamp
>Дата и время проводки Входящий остаток
>08.05.2010 08:39:16 -842783,49
с такими данными неудобно работать
>было бы отлично, если бы привели пример исходных данных(напр., >Игорь Шевченко © (24.11.10 20:36) [2]) и тех, что нужно получить.
Inovet (2010-11-26 20:41:00) [22]> [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
Игорь Шевченко (2010-11-26 14:11:00) [23]решение из [2] никак ? заменив MIN на MAX
Насколько я вижу, у тебя остаток все время уменьшается в течение одной даты.
xmen (2010-11-26 10:22:00) [24]
> >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
Кщд (2010-11-26 08:03:00) [25]>Inovet © (25.11.10 16:09) [7]
тот вариант, что предложили Вы, не просто не вернет нужного результата(т.е. это аналог select your_date, rem from tbl:)), но даже не будет выполняться
не только на Oracle
Кщд (2010-11-26 07:42:00) [26]>xmen (25.11.10 17:17) [8]
1. трижды обращаетесь к одной и той же таблице;
2. неаккуратно используете псевдонимы;
3. лишние преобразования date-char-date - несмотря на то, что Вам в этой ветке рассказали о trunc
4. с какой целью использован rownum?
было бы отлично, если бы привели пример исходных данных(напр., Игорь Шевченко © (24.11.10 20:36) [2]) и тех, что нужно получить.
xmen (2010-11-25 17:17:00) [27]Всем спасибо, попробую предложенные варианты.
После того как запостил вопрос написал свое решение, оно почему-то очень громоздкое:
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'))
Inovet (2010-11-25 16:09:00) [28]> [6] Кщд (25.11.10 11:16)
> если нужно на КАЖДУЮ строку, то двойной FTS - самый последний
> вариант и можно делать так, как предлагал Игорь Шевченко
> - через аналитику:
Я особенносте Оракл не знаю, поэтому и написал "как-то так".
Кщд (2010-11-25 11:16:00) [29]>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
Кщд (2010-11-25 10:34:00) [30]>Получение остатков на каждую дату
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)
Игорь Шевченко (2010-11-24 23:47:00) [31]
> потому что 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
Inovet (2010-11-24 22:18:00) [32]> [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
;
Игорь Шевченко (2010-11-24 20:36:00) [33]Или я что-то не понял или без аналитики где-то так:
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);
Игорь Шевченко (2010-11-24 20:25:00) [34]Возможно, с использованием аналитических функций.