How to get one query about sales set on default date? - oracle

I have two tables, T_TEST and T_DEFAULT_DATE. T_TEST contains date and amount, and T_DEFAULT_DATE contains just P_DATE.
First table T_TEST:
DATE AMOUNT
-------- ----------
01.01.99 77
16.02.99 59
01.01.00 12
15.01.00 32
01.02.00 144
15.02.00 320
16.02.00 521
01.03.00 98
15.03.00 76
16.03.00 33
01.01.01 65
15.01.01 78
01.02.01 95
15.02.01 39
16.02.01 97
02.02.02 63
07.03.02 75
And second table T_DEFAULT_DATE:
P_DATE
--------
16.02.01
What I want to get is two queries established in a single query :
1. what is the amount of sale achieved on the same day last year (- 12 mounths)
2. amount of sales for whole past year (based on table T_DEFAULT_DATE)
3. the amount (sum) for whole mounth (default mounth : 1.2. 2001 - 28.2.2001)
Expected output is :
P_SDLY P_LY P_MS
-----------
521 1236 231
I tryed with add_months(t_default_date.p_date, -12) , but I didn't get expected result. Please help

You can try something like this, assuming that your fields are stored in date columns.
SQL> with t_test(date_, amount) as
2 (
3 select to_date('01.01.99', 'dd.mm.rr'), 77 from dual union all
4 select to_date('16.02.99', 'dd.mm.rr'), 59 from dual union all
5 select to_date('01.01.00', 'dd.mm.rr'), 12 from dual union all
6 select to_date('15.01.00', 'dd.mm.rr'), 32 from dual union all
7 select to_date('01.02.00', 'dd.mm.rr'), 144 from dual union all
8 select to_date('15.02.00', 'dd.mm.rr'), 320 from dual union all
9 select to_date('16.02.00', 'dd.mm.rr'), 521 from dual union all
10 select to_date('01.03.00', 'dd.mm.rr'), 98 from dual union all
11 select to_date('15.03.00', 'dd.mm.rr'), 76 from dual union all
12 select to_date('16.03.00', 'dd.mm.rr'), 33 from dual union all
13 select to_date('01.01.01', 'dd.mm.rr'), 65 from dual union all
14 select to_date('15.01.01', 'dd.mm.rr'), 78 from dual union all
15 select to_date('01.02.01', 'dd.mm.rr'), 95 from dual union all
16 select to_date('15.02.01', 'dd.mm.rr'), 39 from dual union all
17 select to_date('16.02.01', 'dd.mm.rr'), 97 from dual union all
18 select to_date('02.02.02', 'dd.mm.rr'), 63 from dual union all
19 select to_date('07.03.02', 'dd.mm.rr'), 75 from dual
20 ),
21 t_default_date(p_date) as
22 (
23 select to_date('16.02.01', 'dd.mm.rr') from dual
24 )
25 select sum(
26 case
27 when date_ between add_months(trunc(p_date, 'yyyy'), -12)
28 and trunc(p_date, 'yyyy')-1
29 then amount
30 else 0
31 end
32 ) as year,
33 sum( decode (date_, add_months(p_date, -12), amount, 0) ) as day,
34 sum( case
35 when date_ between
36 trunc(p_date, 'MM') and
37 last_day(p_date)
38 then amount
39 else
40 0
41 end
42 ) as month
43 from t_test
44 inner join t_default_date on (date_ between add_months(trunc(p_date, 'yyyy'), -12) and last_day(p_date) );
YEAR DAY MONTH
---------- ---------- ----------
1236 521 231
SQL>
This makes use of add_months to get exactly "one year ago"; if you need "365 days ago" (think of leap years), consider using something like date - 365

Related

How to query date differences between dates of same column?

I have a table with a date field and I need a query to return the ID of records that are on a certain day.
Example
ID UPDATED_DATE
42 31-DEC-19 12.00.00.000000000 AM
43 24-DEC-19 12.00.00.000000000 AM
44 03-DEC-19 12.00.00.000000000 AM
45 18-NOV-19 12.00.00.000000000 AM
46 08-NOV-19 12.00.00.000000000 AM
47 01-NOV-19 12.00.00.000000000 AM
48 26-OCT-19 12.00.00.000000000 AM
49 04-OCT-19 12.00.00.000000000 AM
50 20-SEP-19 12.00.00.000000000 AM
I need a query to find if the DAY part of the date is >= 1 and < 5.
In the example, I will get the ID as 44, 47 and 49 as output.
Can anyone help me for the query, please?
Use TO_CHAR with appropriate format mask:
SQL> alter session set nls_date_format = 'dd.mm.yyyy';
Session altered.
SQL> with test as
2 (select 42 id, date '2019-12-31' updated_date from dual union all
3 select 43, date '2019-12-24' from dual union all
4 select 44, date '2019-12-03' from dual union all
5 select 45, date '2019-11-18' from dual union all
6 select 46, date '2019-11-08' from dual union all
7 select 47, date '2019-11-01' from dual union all
8 select 48, date '2019-10-26' from dual union all
9 select 49, date '2019-10-04' from dual union all
10 select 50, date '2019-09-20' from dual
11 )
12 select id, updated_date, to_char(updated_date, 'fmdd') dd
13 from test
14 where to_char(updated_date, 'fmdd') >= 1
15 and to_char(updated_date, 'fmdd') < 5
16 order by id;
ID UPDATED_DA DD
---------- ---------- --
44 03.12.2019 3
47 01.11.2019 1
49 04.10.2019 4
SQL>
If you want the difference (as per the original version of the question) between day-of-month of two rows to be between 1 and 4 days then use LAG/LEAD:
SELECT ID,
UPDATED_DATE
FROM (
SELECT ID,
UPDATED_DATE,
EXTRACT(DAY FROM updated_date) AS day,
LAG( EXTRACT(DAY FROM updated_date) )
OVER ( ORDER BY EXTRACT(DAY FROM updated_date) ) AS prev_day,
LEAD( EXTRACT(DAY FROM updated_date) )
OVER ( ORDER BY EXTRACT(DAY FROM updated_date) ) AS next_day
FROM table_name
)
WHERE day - prev_day BETWEEN 1 AND 4
OR next_day - day BETWEEN 1 AND 4
Which for your test data ouptuts:
ID | UPDATED_DATE
-: | :--------------------
47 | 01-NOV-19 12:00:00 AM
44 | 03-DEC-19 12:00:00 AM
49 | 04-OCT-19 12:00:00 AM
46 | 08-NOV-19 12:00:00 AM
45 | 18-NOV-19 12:00:00 AM
50 | 20-SEP-19 12:00:00 AM
43 | 24-DEC-19 12:00:00 AM
48 | 26-OCT-19 12:00:00 AM
If you want the day-of-month to be between 1 and 4 then use EXTRACT:
SELECT *
FROM table_name
WHERE EXTRACT(DAY FROM updated_date) BETWEEN 1 AND 4
Which outputs:
ID | UPDATED_DATE
-: | :--------------------
44 | 03-DEC-19 12:00:00 AM
47 | 01-NOV-19 12:00:00 AM
49 | 04-OCT-19 12:00:00 AM
db<>fiddle here

Oracle - How to know the load volume by times of a table?

I have some tables in Oracle and I would like to know the variations of the table by sections of time.
I explain, I need a query/script to know how often data is loaded / updated in the table.
example
Can anyone give me ideas on how to do something like that or similar?
Thanks!
Split a day to hours (CTEs times and periods) and apply aggregates to values stored in your_table (which is joined to "fabricated" hours). For example:
SQL> with times as
2 (select trunc(sysdate) + (level - 1)/24 val
3 from dual
4 connect by level <= 25
5 ),
6 periods as
7 (select val val_from,
8 lead(val) over (order by val) val_to
9 from times
10 ),
11 your_table (date_column, ins, upd) as
12 (select trunc(sysdate) + 13/24 + 25/(24*60), 100, 18 from dual union all
13 select trunc(sysdate) + 13/24 + 25/(24*60), 225, null from dual union all
14 select trunc(sysdate) + 14/24 + 33/(24*60), 203, 112 from dual union all
15 select trunc(sysdate) + 15/24 + 15/(24*60), null, 687 from dual union all
16 select trunc(sysdate) + 15/24 + 18/(24*60), null, 987 from dual
17 )
18 select to_char(p.val_from, 'hh24:mi') ||' - '||
19 to_char(p.val_to , 'hh24:mi') period,
20 count(ins) cnt_insert,
21 count(upd) cnt_update
22 from periods p join your_table t on t.date_column >= p.val_from
23 and t.date_column < p.val_to
24 where p.val_to is not null
25 group by p.val_from, p.val_to
26 order by p.val_From;
PERIOD CNT_INSERT CNT_UPDATE
------------- ---------- ----------
13:00 - 14:00 2 1
14:00 - 15:00 1 1
15:00 - 16:00 0 2
SQL>

hive - inserting rows for different column value

Honestly, I don't know how simply I can describe the question on the title line instead of showing an example.
I have a hive table which contains two columns: ID and date
ID Date
31 01-01-2017
31 01-02-2017
31 01-03-2017
123 01-01-2017
123 01-01-2017
...
In this table, I would like to include another column which is hour such as below
ID Date Hour
31 01-01-2017 00
31 01-01-2017 01
31 01-01-2017 02
31 01-01-2017 03
31 01-01-2017 04
...
31 01-01-2017 23
31 01-02-2017 00
31 01-02-2017 01
...
Basically, for every row, I would like add an hour column of values from 00 to 23.
Can this be achieved using hive?
Thank you so much.
You could create a temporary table which contains entries from 0 to 23 and do a cross join with the table you have. Or you can leverage on the CTE function a CTE table with entries from 0 to 23 and then do a cross join with it.
An example:
with temp as (
select 0 hour union all
select 1 hour union all
select 2 hour union all
select 3 hour union all
select 4 hour union all
select 5 hour union all
select 6 hour union all
select 7 hour union all
select 8 hour union all
select 9 hour union all
select 10 hour union all
select 11 hour union all
select 12 hour union all
select 13 hour union all
select 14 hour union all
select 15 hour union all
select 16 hour union all
select 17 hour union all
select 18 hour union all
select 19 hour union all
select 20 hour union all
select 21 hour union all
select 22 hour union all
select 23 hour
)
select * from table join temp
You can also insert the result into a table to persist the result. Hope it helps

Get subobject of object in hierarchy

with sample_data as (select '26.03.2015 14:10' as adate, 4 as type, 40 as object, 111 as barcode from dual union all
select '26.03.2015 14:09' as adate, 1 as type, 55 as object, 222 as barcode from dual union all
select '26.03.2015 14:08' as adate, 2 as type, 33 as object, 777 as barcode from dual union all
select '26.03.2015 14:08' as adate, 2 as type, 34 as object, null as barcode from dual union all
select '26.03.2015 13:20' as adate, 3 as type, 41 as object, null as barcode from dual union all
select '26.03.2015 12:00' as adate, 1 as type, 56 as object, 444 as barcode from dual union all
select '26.03.2015 11:59' as adate, 2 as type, 37 as object, 555 as barcode from dual union all
select '26.03.2015 11:59' as adate, 2 as type, 48 as object, null as barcode from dual)
select
adate, type, object, barcode
from sample_data
where type in (1, 2);
type 1 is finished building, type 2 is part of assembly
i need next result
55 | 222 | 26.03.2015 14:08 | 33
55 | 222 | 26.03.2015 14:08 | 34
56 | 444 | 26.03.2015 11:59 | 37
56 | 444 | 26.03.2015 11:59 | 38
so we see what object 55 contain subobject 33, 34 and two date = 26.03.2015 14:08
and object 56 contain subobject 37, 38 and two date = 26.03.2015 11:59
in begin i know two parameters - date and barcode of finished building, for example on my data - date 26.03.2015 14:09 and barcode 222 or date 26.03.2015 12:00 and barcode 444
This query does the job. Subquery T1 connects "types 1" with "types 2". T2 enumerates them using function row_number().
Last query filters only rows with rn = 1.
with t1 as (
select t.*, prior object pob, prior barcode pbc,
prior adate pad, level, sys_connect_by_path(object, '-') pth
from sample_data t where level=2
connect by prior adate > adate and prior type = 1 and type = 2),
t2 as (select t1.*,
row_number() over (partition by object order by pad) rn from t1 )
select pob, pbc, adate, object from t2 where rn = 1
Result:
POB PBC ADATE OBJECT
---------- ---------- ------------------- ----------
55 222 2015-03-26 14:08:00 33
55 222 2015-03-26 14:08:00 34
56 444 2015-03-26 11:59:00 37
56 444 2015-03-26 11:59:00 48
you have to define groups and then you can assign the items to the groups
with sample_data as (select '26.03.2015 14:10' as adate, 4 as type, 40 as object, 111 as barcode from dual union all
select '26.03.2015 14:09' as adate, 1 as type, 55 as object, 222 as barcode from dual union all
select '26.03.2015 14:08' as adate, 2 as type, 33 as object, 777 as barcode from dual union all
select '26.03.2015 14:08' as adate, 2 as type, 34 as object, null as barcode from dual union all
select '26.03.2015 13:20' as adate, 3 as type, 41 as object, null as barcode from dual union all
select '26.03.2015 12:00' as adate, 1 as type, 56 as object, 444 as barcode from dual union all
select '26.03.2015 11:59' as adate, 2 as type, 37 as object, 555 as barcode from dual union all
select '26.03.2015 11:59' as adate, 2 as type, 48 as object, null as barcode from dual),
sd_groups as (select adate, lag(adate, 1) over (order by adate) adate_last, object, barcode from (
select * from sample_data where type = 1
union all select min(adate), null, null, null from sample_data))
select sg.object, sg.barcode, sd.adate, sd.object
from sample_data sd, sd_groups sg
where sd.type = 2 and sd.adate between sg.adate_last and sg.adate;

To find how many questions answered by number of user in an hour

I have a requirement to show 1 to 20 questions how many teams answered for 0-23 hours. The table structure
Team_id Question_id Updated
124 25092 02-SEP-14 11:30:12 AM
15 25076 02-SEP-14 02:31:15 PM
258 25061 02-SEP-14 03:02:33 PM
298 25196 02-SEP-14 03:32:49 PM
450 25203 02-SEP-14 07:01:05 PM
471 25351 02-SEP-14 07:47:31 PM
482 25350 02-SEP-14 08:01:03 PM
78 24924 02-SEP-14 08:01:29 PM
541 26032 02-SEP-14 09:35:00 PM
708 26485 02-SEP-14 12:19:48 PM
726 26125 02-SEP-14 01:00:11 PM
145 26221 02-SEP-14 03:45:32 PM
824 26436 02-SEP-14 06:30:16 PM
87 26505 02-SEP-14 06:30:22 PM
825 26488 02-SEP-14 06:31:34 PM
466 26488 02-SEP-14 06:34:48 PM
868 26091 02-SEP-14 08:30:59 PM
1356 28852 02-SEP-14 07:45:14 PM
1342 28852 02-SEP-14 07:45:27 PM
Query should return
Hours 1 2 3 4 5 to 20
10 6 0 2 3 6 to 25
11 3 2 1 1 7 to 300
12 2 0 5 0 7 to 30
13 1 6 1 1 7 to 40
these are count of team that answered only 1 question in hour 10
these are count of team that answered only 2 question in hour 10 etc.
Note it is not 1st or 2nd question.
Thanks
Arun
You need something like this I suppose:
select hour,
count(decode(cnt, 1, 1)) as q1,
count(decode(cnt, 2, 1)) as q2,
count(decode(cnt, 3, 1)) as q3,
count(decode(cnt, 4, 1)) as q4,
...
count(decode(cnt, 20, 1)) as q20
from (
select to_char(updated, 'HH24') as hour
, count(*) as cnt
from &table_name
group by to_char(updated, 'HH24'), team_id
)
group by hour;
As far as I understand, perhaps you want something like this :
SQL> WITH DATA AS(
2 SELECT 124 team_id, 25092 question_id, to_date('02-SEP-14 11:30:12 AM','DD-MON-RR HH:MI:SS AM') UPDATED FROM DUAL UNION ALL
3 SELECT 15 , 25076 ,to_date('02-SEP-14 02:31:15 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL UNION ALL
4 SELECT 258 , 25061 ,to_date('02-SEP-14 03:02:33 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL UNION ALL
5 SELECT 298 , 25196 ,to_date('02-SEP-14 03:32:49 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL UNION ALL
6 SELECT 450 , 25203 ,to_date('02-SEP-14 07:01:05 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL UNION ALL
7 SELECT 471 , 25351 ,to_date('02-SEP-14 07:47:31 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL UNION ALL
8 SELECT 482 , 25350 ,to_date('02-SEP-14 08:01:03 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL UNION ALL
9 SELECT 78 , 24924 ,to_date('02-SEP-14 08:01:29 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL UNION ALL
10 SELECT 541 , 26032 ,to_date('02-SEP-14 09:35:00 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL UNION ALL
11 SELECT 708 , 26485 ,to_date('02-SEP-14 12:19:48 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL UNION ALL
12 SELECT 726 , 26125 ,to_date('02-SEP-14 01:00:11 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL UNION ALL
13 SELECT 145 , 26221 ,to_date('02-SEP-14 03:45:32 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL UNION ALL
14 SELECT 824 , 26436 ,to_date('02-SEP-14 06:30:16 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL UNION ALL
15 SELECT 87 , 26505 ,to_date('02-SEP-14 06:30:22 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL UNION ALL
16 SELECT 825 , 26488 ,to_date('02-SEP-14 06:31:34 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL UNION ALL
17 SELECT 466 , 26488 ,to_date('02-SEP-14 06:34:48 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL UNION ALL
18 SELECT 868 , 26091 ,to_date('02-SEP-14 08:30:59 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL UNION ALL
19 SELECT 1356 , 28852 ,to_date('02-SEP-14 07:45:14 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL UNION ALL
20 SELECT 1342 , 28852 ,to_date('02-SEP-14 07:45:27 PM','DD-MON-RR HH:MI:SS AM') FROM DUAL)
21 SELECT 5 hours,
22 COUNT(team_id)
23 FROM DATA
24 WHERE UPDATED BETWEEN to_date('02-SEP-14 10:00:01','DD-MON-RR HH24:MI:SS') AND to_date('02-SEP-14 14:59:59','DD-MON-RR HH24:MI:SS')
25 UNION
26 SELECT 6 hours,
27 COUNT(team_id)
28 FROM DATA
29 WHERE UPDATED BETWEEN to_date('02-SEP-14 10:00:01','DD-MON-RR HH24:MI:SS') AND to_date('02-SEP-14 15:59:59','DD-MON-RR HH24:MI:SS')
30 UNION
31 SELECT 10 hours,
32 COUNT(team_id)
33 FROM DATA
34 WHERE UPDATED BETWEEN to_date('02-SEP-14 10:00:01','DD-MON-RR HH24:MI:SS') AND to_date('02-SEP-14 19:59:59','DD-MON-RR HH24:MI:SS')
35 UNION
36 SELECT 24 hours,
37 COUNT(team_id)
38 FROM DATA
39 WHERE UPDATED BETWEEN to_date('02-SEP-14 00:00:01','DD-MON-RR HH24:MI:SS') AND to_date('02-SEP-14 23:59:59','DD-MON-RR HH24:MI:SS')
40 /
HOURS COUNT(TEAM_ID)
---------- --------------
5 4
6 7
10 15
24 19
The time interval as an example, I took varying intervals, and the HOURS column is the time interval mentioned in the WHERE clause.

Resources