Creating fact table with year of 9999 - oracle

I'm building a simple fact table in oracle based on a customer status where a customer has a status, 'Active' and 'Lost' and a date they started with that status and a date they ended.
A sample 3 rows would be;
CustID | status | date_start | date_end
---------------------------------------
1 | active | 1/1/13 | 1/12/14
1 | lost | 1/12/14 | 31/12/9999
2 |active | 1/12/14 | 31/12/9999
Here, cust 1 was active and then was lost. When a account status is current (as of today) the end date column is 31/12/9999. Cust 2 is active as of today
My question is, how can I bring this into a fact table?
CREATE TABLE temp AS
SELECT CS.contract_status_id , to_char(ASH.Contract_Status_Start, 'DD/MM/YYYY') AS cust_status_start_date, to_char(ASH.CONTRACT_STATUS_END, 'DD/MM/YYYY') As cust_status_end_date
FROM account_status_history ASH,
customer_status_dim CS
WHERE ASH.contract_status = CS.contract_status
Fact Table:
CREATE TABLE customer_status_fact AS
SELECT T.cust_status_start_date, T.cust_status_end_date, T.contract_status_id,
count(T.contract_status_id) AS TOTAL_ACCOUNTS
FROM temp T
GROUP BY T.cust_status_start_date, T.cust_status_end_date, T.contract_status_id
And testing it;
select sum(F.TOTAL_ACCOUNTS), CS.contract_status_txt
from customer_status_fact F, customer_status_dim CS
where F.contract_status_id = CS.contract_status_id
and F.cust_status_start_date <= sysdate
and F.cust_status_end_date = '31/12/9999'
group by CS.contract_status_txt
I can't seem to get oracle to recognise the year 9999 Any help is appreciated

and F.cust_status_end_date = '31/12/9999'
'31/12/9999' is NOT a DATE, it is a string enclosed within single-quotation marks. You must use TO_DATE to explicitly convert it into a DATE.
For example,
SQL> alter session set nls_date_format='DD/MM/YYYY HH24:MI:SS';
Session altered.
SQL> SELECT to_date('31/12/9999 23:59:59','DD/MM/YYYY HH24:MI:SS') FROM dual;
TO_DATE('31/12/9999
-------------------
31/12/9999 23:59:59
SQL>
OR,
SQL> SELECT to_date(5373484, 'J') + (1 - 1/24/60/60) FROM dual;
TO_DATE(5373484,'J'
-------------------
31/12/9999 23:59:59
SQL>
CREATE TABLE temp AS SELECT CS.contract_status_id ,
to_char(ASH.Contract_Status_Start, 'DD/MM/YYYY') AS
cust_status_start_date, to_char(ASH.CONTRACT_STATUS_END, 'DD/MM/YYYY')
As cust_status_end_date
Why would you create a table with DATEs converted to a STRING? You should let the dates as it is. You should use TO_CHAR only for display purpose. For any date calculations, let the date remain as a date.

Related

Charts in Oracle Apex

Hi everyone I wanna ask u about how I can bring data last 24 hours into bar charts, is there any methods to make it please
I have this table without data
datetime
clientchannel
servicename
service_count
13_02_2022 9:35
*****
notification
2
It is a WHERE clause you need, I presume. Something like this:
select ...
from your_table
where datetime >= sysdate - 1;
Why? Because - when you subtract a number from DATE datatype value in Oracle - it subtracts that many days.
SQL> alter session set nls_date_format = 'dd.mm.yyyy hh24:mi:ss';
Session altered.
SQL> select sysdate right_now,
2 sysdate - 1 yesterday
3 from dual;
RIGHT_NOW YESTERDAY
------------------- -------------------
13.02.2022 11:01:34 12.02.2022 11:01:34
SQL>
If you store date values as strings (which means that DATETIME column is declared as e.g. VARCHAR2(20), and that's really bad idea), then you first have to convert it to a valid date datatype value - use TO_DATE function with appropriate format mask:
where to_date(datetime, 'dd_mm_yyyy hh24:mi') >= sysdate - 1
[EDIT] If you want to go 60 minutes back, then subtract that many minutes:
SQL> select sysdate right_now,
2 sysdate - interval '60' minute an_hour_ago
3 from dual;
RIGHT_NOW AN_HOUR_AGO
------------------- -------------------
14.02.2022 07:09:30 14.02.2022 06:09:30
SQL>

How to select records from Oracle Database where 2 dates are not in same month and year

How to select records from Oracle Database where 2 dates are not in same month and year.
Below table is example, here I want all records where created date and updated date are not in same month and year.
The value for both date field in millisecond (ex.1454738400000) and
Data type of both date field is NUMBER(32).
---------------------------------
id| Created Date | Updated Date |
---------------------------------
1 | 02/26/2018 | 02/26/2017 |
---------------------------------
2 | 03/28/2018 | 03/26/2018 |
---------------------------------
3 | 04/26/2018 | 04/28/2017 |
---------------------------------
4 | 02/26/2018 | 02/26/2016 |
---------------------------------
Have a look at these two options:
select record_id
from your_table
where to_char(created_date, 'mm.yyyy') <> to_char(updated_date, 'mm.yyyy');
select record_id
from your_table
where trunc(created_date, 'yyyy') <> trunc(updated_date, 'yyyy')
and trunc(created_date, 'mm') <> trunc(updated_date, 'mm');
If there's a lot of data involved, consider creating a function-based index(es) on DATE columns.
[EDIT]
If those values really are numbers, then you have to convert them to DATE datatype first, then apply TRUNC function. For example:
SQL> select trunc(to_date(20190226, 'yyyymmdd'), 'yyyy') result from dual;
RESULT
----------
01.01.2019
SQL>
Note that it'll fail if format is wrong, for example 20190231 (which is supposed to be 31st of February 2019) as there aren't 31 days in February.
If possible, change those columns' datatype to DATE.

oracle concat timestmap from current_date

I hardly try to concat timestamps. Column time, defined as varchar2, contains values like 23:15. Now I want to create a timestamp with today's date and that time, in this example 23.03.18 23:15:00.00000 is expected. The way I'm doing this is
to_timestamp(to_char(trunc(current_date),'ddMMyyyy') ||
to_char(time),'dd.MM.yyyy hh24:mi:ss')
and it works. But when field time has value 06:15, I get the message "hour must be between 0 and 23 ". Whatever I try, it's always this message when time value has leading zero. How can that be corrected?
You don't need to use TRUNC on the current date as the TO_CHAR will extract only the year-to-day components and you also don't need TO_CHAR on the time column as it is already a string. Apart from those simplifications, your query works:
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE times ( time ) AS
SELECT '00:00' FROM DUAL UNION ALL
SELECT '06:45' FROM DUAL UNION ALL
SELECT '12:00' FROM DUAL UNION ALL
SELECT '18:59' FROM DUAL UNION ALL
SELECT '23:15' FROM DUAL;
Query 1:
SELECT time,
TO_TIMESTAMP(
TO_CHAR( CURRENT_DATE, 'YYYY-MM-DD' ) || time,
'YYYY-MM-DDHH24:MI'
) AS current_day_time
FROM times
Results:
| TIME | CURRENT_DAY_TIME |
|-------|-----------------------|
| 00:00 | 2018-03-23 00:00:00.0 |
| 06:45 | 2018-03-23 06:45:00.0 |
| 12:00 | 2018-03-23 12:00:00.0 |
| 18:59 | 2018-03-23 18:59:00.0 |
| 23:15 | 2018-03-23 23:15:00.0 |
Works OK for me:
SQL> WITH test
2 AS (SELECT '23:15' time FROM DUAL
3 UNION
4 SELECT '06:15' time FROM DUAL)
5 SELECT TO_TIMESTAMP (
6 TO_CHAR (CURRENT_DATE, 'ddMMyyyy') || time,
7 'dd.MM.yyyy hh24:mi:ss') result
8 FROM test;
RESULT
----------------------------------------------------------------
23.03.18 06:15:00,000000000
23.03.18 23:15:00,000000000
SQL>
Please, post your SQL*Plus session so that we could see what you did.
try other way around: insert a leading 0 if hour < 10
to_timestamp(to_char(trunc(current_date),'ddMMyyyy') ||
to_char(
case when substr(time,1,instr(time,':',1,1)-1)<10
then'0'||time
else time
end),'dd.MM.yyyy hh24:mi:ss')

Finding summary & basic statistics from data in Vertica

Recently I am exploring HPE Vertica a bit. Is it possible to find summary statistics (mean,sd,quartiles,max,min,counts etc) from a data table loaded in vertica?
These two links;
https://my.vertica.com/docs/7.0.x/HTML/Content/Authoring/SQLReferenceManual/Functions/VerticaFunctions/ANALYZE_STATISTICS.htm
https://my.vertica.com/docs/7.0.x/HTML/Content/Authoring/SQLReferenceManual/Functions/VerticaFunctions/ANALYZE_HISTOGRAM.htm
say that we can find statistics & histogram from the data but the result is making no sense to me.
According to it, the ANALYZE_STATISTICS command will throw a 0 for successful execution. Like
NEWDB_aug17=> SELECT ANALYZE_STATISTICS ('MM_schema.capitalline');
ANALYZE_STATISTICS
--------------------
0
(1 row)
Here NEWDB_aug17 is the database, schema is MM_schema under which capitalline table was inserted. But where are the summary measures, i mean the numbers we are actually looking for? Only a 0 is not going to serve my purpose.
Can you please guide me in this context?
Vertica saves the statistics collected by ANALYZE_STATISTICS() in the catalog location.
These statistics are later used to calculate best query execution plan.
You can find the statistics details in the system table v_internal.dc_analyze_statistics
[dbadmin#vertica-1 ~]$ vsql
dbadmin=> \x
Expanded display is on.
dbadmin=> select * from v_internal.dc_analyze_statistics limit 1;
-[ RECORD 1 ]----+-----------------------------------
time | 2017-08-21 02:07:03.287895+00
node_name | v_test_node0001
session_id | v_test_node0001-502811:0x834a4
user_id | 45035996273704962
user_name | dbadmin
transaction_id | 45035996307673368
statement_id | 9
request_id | 1
table_name | test_table
proj_column_name | test_column
proj_name | test_table_sp_v11_b1
table_oid | 45036013037102108
proj_column_oid | 45036013037111264
proj_row_count | 119878353211
disk_percent | 10
disk_read_rows | 11987835321
sample_rows | 131072
sample_bytes | 7602176
start_time | 2017-08-21 02:07:03.657377+00
end_time | 2017-08-21 02:07:24.799398+00
Time: First fetch (1 row): 849.467 ms. All rows formatted: 849.594 ms
Or at this path:
{your_catalog_location}/{db_name}/{node_name}_catalog/DataCollector/AnalyzeStatistics_*.log
percentile_cont function of Vertica would be helpful in retrieving quartile.
create table test
(metric_value integer);
insert into test values(1);
insert into test values(2);
insert into test values(3);
insert into test values(4);
insert into test values(5);
insert into test values(6);
insert into test values(7);
insert into test values(8);
insert into test values(9);
insert into test values(10);
alter table anatest add column metric varchar(100) default 'abc';
select
metric_value,
percentile_cont(1) within group (order by metric_value) over (partition by metric) as max,
percentile_cont(.75) within group (order by metric_value ) over (partition by metric) as q3,
percentile_cont(.5) within group (order by metric_value ) over (partition by metric) as median,
percentile_cont(.25) within group (order by metric_value ) over (partition by metric) as q1,
percentile_cont(0) within group (order by metric_value ) over (partition by metric) as min
from test ;

Oracle find record if the given date is within the range

I need to get the daily schedule for the tasks done by people.
The data in my db is stored like this
sno | start_date_time | end_date_time |
---------------------------------------------------
1 |06-10-2016 09:30:00 | 06-10-2016 17:00:00 |
2 |12-10-2016 08:00:00 | 15-10-2016 13:00:00 |
My question is if i give a date for example 14-10-2016 I would like to get the second record.
I dont know how to query it since the given date does not fall into start_date_time or end_date_time
Is it possible to do that in oracle?
Try between
select * from your_table
where your_date between start_date_time and end_date_time
Example:
select * from (
select '2016-01-05' as t1, '2016-02-05' as t2
union all
select '2016-05-05' as t1, '2016-08-05' as t2
) a
where '2016-02-01' between t1 and t2
gives
t1 t2
2016-01-05 2016-02-05
Of course this also works not only for dates but also for timestamps.
Keep in mind that when comparing dates and timestamp the date is casted as a
timestamp like this '2016-01-01' -> '2016-01-01 00:00:00'
Usually start and end dates allow null values, so apart from between in PhillipsD answer you might also need nvl:
select * from your_table
where your_date between nvl(start_date_time, your_date) and nvl(end_date_time, your_date)

Resources