Oracle - Selecting not null result of calculation - oracle

For every row of my data set, there exist data for the only one of the two options for calculation and the other columns are Null.
My goal is to find simplest way to select not null result of calculation for each row. Expected result:
ROW_NUM result
-------- -------
1 4.5
2 4.56
My code:
With DATASET AS (
-- column 1 is just for row number,
-- column 2 and 3 for caculation option1,
--- columns 4~6 for caculation option2
SELECT 1 ROW_NUM, NULL time1, NULL qty1, 2 time2_1, 2.5 time2_2, 1 qty2
FROM DUAL
UNION
SELECT 2 ROW_NUM, 4.56 time1, 1 qty1, NULL time2_1, NULL time2_2, NULL qty2
FROM DUAL
)
SELECT ROW_NUM, time1/qty1 OPTION1, (time2_1+time2_2)/qty2 OPTION2
FROM DATASET;
Result:
ROW_NUM OPTION1 OPTION2
-------- ------- ---------
1 4.5
2 4.56

You can decode and use different representation when null:
SELECT ROW_NUM, decode(time1/qty1,null,(time2_1+time2_2)/qty2,time1/qty1) result FROM DATASET;
Or nvl
SELECT ROW_NUM, nvl(time1/qty1,(time2_1+time2_2)/qty2,time1/qty1) result FROM DATASET;
NVL lets you replace null (returned as a blank) with a string in the results of a query.

use COALESCE function as following:
With DATASET AS (
--each row contain information for either option1 or 2
SELECT *
FROM
(
--column 1 is just for row number, column 2 and 3 for caculation option1, columns 4~6 for caculation option2
SELECT 1 ROW_NUM, NULL time1, NULL qty1 , 2 time2_1 , 2.5 time2_2, 1 qty2 FROM DUAL
UNION
SELECT 2 ROW_NUM, 4.56 time1 , 1 qty1 , NULL time2_1 , NULL time2_2 , NULL qty2 FROM DUAL
)
)SELECT ROW_NUM, coalesce(time1/qty1,(time2_1+time2_2)/qty2) as result FROM DATASET;
db<>fiddle demo
Cheers!!

Related

Sum 2 columns from multiple rows with same ID

Currently, I have a table MY_TABLE like below:
ID ACCT_TYPE CREDIT_AMT DEBIT_AMT
-- --------- ---------- ---------
1 CDT_01 4 (null)
1 DBT_01 (null) 6
One ID can have multiple ACCT_TYPE like above, and each type has its own amount.
I want to just select the row which has ACCT_TYPE like 'CDT_%' but also the total_amount column which is the total of credit_amt and debit_amt column for the same ID.
My expected output like below:
ID ACCT_TYPE TOTAL_AMT
-- --------- ---------
1 CDT_01 10
I tried with this select statement below but it's no use, I think it's because of different ACCT_TYPE:
Select ID, ACCT_TYPE, SUM(NVL(CREDIT_AMT, 0) + NVL(DEBIT_AMT, 0)) TOTAL_AMT
FROM MY_TABLE WHERE ACCT_TYPE LIKE 'CDT_%' GROUP BY ID, ACCT_TYPE;
Here is the output of the select statement above:
ID ACCT_TYPE TOTAL_AMT
-- --------- ---------
1 CDT_01 4
I just begin to learn some query so I don't know is it really possible to get my expected output.
One way to do it is like below:
with inputs (ID, ACCT_TYPE, CREDIT_AMT, DEBIT_AMT) as
(
select 1, 'CDT_01', 4, null from dual union all
select 1, 'DBT_01', null, 6 from dual
),
prep as
(
select t.*, sum(nvl(credit_amt,0)) over (partition by id) + sum(nvl(debit_amt,0)) over (partition by id) as sum_per_id
from inputs t
)
select id, acct_type, sum_per_id
from prep
where acct_type like 'CDT_%';
Output:
A correlated subquery might be one option; sample data (thank you, #Ranagal) in lines #1 - 5; query that does the job begins at line #6.
SQL> with inputs (ID, ACCT_TYPE, CREDIT_AMT, DEBIT_AMT) as
2 (
3 select 1, 'CDT_01', 4, null from dual union all
4 select 1, 'DBT_01', null, 6 from dual
5 )
6 select a.id,
7 a.acct_type,
8 (select sum(nvl(b.credit_amt, 0)) +
9 sum(nvl(b.debit_amt , 0))
10 from inputs b
11 where b.id = a.id
12 ) total_amt
13 from inputs a
14 where acct_type like 'CDT%';
ID ACCT_T TOTAL_AMT
---------- ------ ----------
1 CDT_01 10
SQL>

display multiple column records in one column in oracle

I have Table having following columns in Oracle;
ID NIC NTN MBL NAME
---------------------------------------
1 1234512 ABC
2 321 XYZ
3 5421 POI
4 541245 624
I need to display like this in select query
ID NIC/NTN/MBL NAME
1 1234512 ABC
2 321 XYZ
3 5421 POI
4 541245 // taking first value
I was trying to do with
SELECT
A.ID,
"CNIC/NTN/MBL"
A.NAME,
A.REASON
B.NAME
FROM TABLEA A
INNER JOIN TABLEB B ON A.R_ID = B.R_ID
UNPIVOT INCLUDE NULLS
(
CNIC/NTN/MBL FOR cols IN (A.NIC, A.NTN, A.MBL)
)
but unable to do.
Use COALESCE:
SELECT
ID,
COALESCE(NIC, NTN, MBL) AS "NIC/NTN/MBL",
NAME
FROM yourTable;
This should work because in the call to COALESCE above, I list the three columns from left to right, and the first non NULL value will be retained.
You need the COALESCE function (which simply returns the first non-null value in the specified inputs, reading from left to right), like so:
WITH your_table AS (SELECT 1 ID, 1234512 nic, NULL ntn, NULL mbl, 'ABC' NAME FROM dual UNION ALL
SELECT 2 ID, NULL nic, 321 ntn, NULL mbl, 'ABC' NAME FROM dual UNION ALL
SELECT 3 ID, NULL nic, NULL ntn, 5421 mbl, 'ABC' NAME FROM dual UNION ALL
SELECT 4 ID, 541245 nic, 624 ntn, NULL mbl, 'ABC' NAME FROM dual)
SELECT ID,
COALESCE(nic, ntn, mbl) nic_ntn_mbl,
NAME
FROM your_table;
ID NIC_NTN_MBL NAME
---------- ----------- ----
1 1234512 ABC
2 321 ABC
3 5421 ABC
4 541245 ABC

Oracle Query to get max of date_column and if null present in that column, then that row should be returned

I had a situation like to read max(end_time_) when delete_reason_ != 'deleted', but when end_time_ has null, the query should return 2nd row only.
SELECT MAX(END_TIME_) FROM TASK_HISTORY WHERE DELETE_REASON_ != 'deleted'
is returning me 1st Row. But, my desired result should return 2nd row. As per Oracle documentation, Aggregate functions like max, sum, min shouldn't consider null values unlike Count.
Is there a way to get the Null value as max if null present, otherwise, max(end_time_) should be my desired output.
Any help will be appreciated.
thank you.
If I understood you correctly, here's one option:
SQL> alter session set nls_date_format = 'dd.mm.yyyy';
Session altered.
SQL> with test (end_time_, delete_reason_) as
2 (select date '2017-12-13', 'completed' from dual union
3 select null, null from dual union
4 select date '2017-12-12', 'deleted' from dual union
5 select date '2018-01-05', 'unknown' from dual
6 ),
7 inter as
8 (select row_number() over (order by end_time_ desc) rn,
9 end_time_, delete_reason_
10 from test
11 where nvl(delete_reason_, 'x') <> 'deleted'
12 )
13 select end_time_ From inter
14 where rn = 1;
END_TIME_
----------
NULL
SQL>
SQL> with test (end_time_, delete_reason_) as
2 (select date '2017-12-13', 'completed' from dual union
3 -- select null, null from dual union
4 select date '2017-12-12', 'deleted' from dual union
5 select date '2018-01-05', 'unknown' from dual
6 ),
7 inter as
8 (select row_number() over (order by end_time_ desc) rn,
9 end_time_, delete_reason_
10 from test
11 where nvl(delete_reason_, 'x') <> 'deleted'
12 )
13 select end_time_ From inter
14 where rn = 1;
END_TIME_
----------
05.01.2018
SQL>
Finally I got a query something like this to achieve null value as result instead of date when I use max() function.
SELECT task_def_key_
, CASE WHEN MAX(CASE WHEN end_time_ IS NULL THEN 1 ELSE 0 END) = 0 THEN MAX(end_time_) END
FROM TASK_HISTORY WHERE DELETE_REASON_ != 'deleted'
GROUP BY task_def_key_
select * from (select * from TASK_HISTORY where DELETE_REASON_ != 'deleted' order by end_time desc) where rownum=1
This will work for your problem

Counting null dates in Oracle

I have a question with null dates in Oracle
I've got a table like this:
ID DATE
1 '02/08/2015'
1 NULL
1 '02/06/2014'
2 NULL
2 '06/02/2013'
This is just an example of the real table. Now what I need is something like this:
ID DAY_INAC
1 1
2 1
I mean, I need to count only the null values present in the DATE column.
But when I execute my query
Select id, count(date)
from table
where date is null
group by Id
having count(date)>0
As a result I'm getting nothing. What do I need to with the date value in order to generate the corresponding counting.
Regards
Because your query is already filtering by date is null, you just need to use count(*)
Select id, count(*)
from table
where date is null
group by Id
having count(*) > 0
COUNT does not count NULL values. You can use CASE to change them:
Select id, count(CASE WHEN date IS NULL THEN 1 END) AS DAY_INAC
from table
where date is null
group by Id;
LiveDemo
Please do not name column as datatypes. Otherwise you may need to quote them.
A more condensed query:
Select id, count(nvl2(date_column,null, sysdate)) as cnt
from table
group by Id;
COUNT will not count NULL values - instead get it to count a literal value (i.e. 1) for those rows that are NULL:
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE table_name ( ID, "DATE" ) AS
SELECT 1, DATE '2015-08-02' FROM DUAL
UNION ALL SELECT 1, NULL FROM DUAL
UNION ALL SELECT 1, DATE '2014-06-02' FROM DUAL
UNION ALL SELECT 2, NULL FROM DUAL
UNION ALL SELECT 2, DATE '2013-02-06' FROM DUAL
Query 1:
SELECT id,
COUNT(1)
FROM table_name
WHERE "DATE" IS NULL
GROUP BY id
Results:
| ID | COUNT(1) |
|----|----------|
| 1 | 1 |
| 2 | 1 |

Oracle: How to count null and non-null rows

I have a table with two columns that might be null (as well as some other columns). I would like to count how many rows that have column a, b, both and neither columns set to null.
Is this possible with Oracle in one query? Or would I have to create one query for each? Can't use group by or some other stuff I might not know about for example?
COUNT(expr) will count the number of rows where expr is not null, thus you can count the number of nulls with expressions like these:
SELECT count(a) nb_a_not_null,
count(b) nb_b_not_null,
count(*) - count(a) nb_a_null,
count(*) - count(b) nb_b_null,
count(case when a is not null and b is not null then 1 end)nb_a_b_not_null
count(case when a is null and b is null then 1 end) nb_a_and_b_null
FROM my_table
Something like this:
SELECT sum(case
when a is null and b is null then 1
else 0
end) as both_null_count,
sum(case
when a is null and b is not null then 1
else 0
end) as only_a_is_null_count
FROM your_table
You can extend that for other combinations of null/not null
select sum(decode(a,null,0,1)) as "NotNullCount", sum(decode(a,null,1,0)) as "NullCount"
from myTable;
Repeat for as many fields as you like.
It can be accomplished in Oracle just in 1 row:
SELECT COUNT(NVL(potential_null_column, 0)) FROM table;
Function NVL checks if first argument is null and treats it as value from second argument.
This worked well for me for counting getting the total count for blank cells on a group of columns in a table in oracle: I added the trim to count empty spaces as null
SELECT (sum(case
when trim(a) is null Then 1
else 0
end)) +
(sum(case
when trim(b) is null
else 0
end)) +
(sum(case
when trim(c) is null
else 0
end)) as NullCount
FROM your_table
Hope this helps
Cheers.
SQL>CREATE TABLE SAMPLE_TAB (COL1 NUMBER NOT NULL, COL2 DATE DEFAULT SYSDATE, COL3 VARCHAR2(20));
SQL>INSERT INTO SAMPLE_TAB(COL1,COL2,COL3) VALUES(121,SYSDATE-2,'SAMPLE DATA');
SQL>INSERT INTO SAMPLE_TAB(COL1,COL2,COL3) VALUES(122,NULL,NULL); --ASSIGN NULL TO COL2
SQL>INSERT INTO SAMPLE_TAB(COL1,COL3) VALUES(123,'SAMPLE DATA RECORD 3');--COL2 DEFAULT VALUE ASSIGN AS SYSDDATE AS PER STRUCTURE.
SQL>COMMIT;
SQL> SELECT * FROM SAMPLE_TAB;
SQL> SELECT *
FROM USER_TAB_COLUMNS U
WHERE 1=1
AND TABLE_NAME='SAMPLE_TAB'
AND NUM_NULLS!=0;
SQL> ANALYZE TABLE SAMPLE_TAB COMPUTE STATISTICS;
SQL> SELECT *
FROM USER_TAB_COLUMNS U
WHERE 1=1
AND TABLE_NAME='SAMPLE_TAB'
AND NUM_NULLS!=0;
One way to do it would be:
select count(*) from table group by nvl2(a, 0, 1), nvl2(b, 0, 1) having nvl2(a,0,1) = nvl2(b,0,1);

Resources