Remove null values from Oracle SQL - sql

I've sql query setup that produces this output:
ID
ID1
ID2
1
123
null
1
234
null
1
456
null
1
null
789
1
null
012
I need the output to be following:
ID
ID1
ID2
1
123
789
1
234
012
1
456
null
Any help will be greatly appreciated.

I have a feeling that this (what you want) should be already done. If that's not possible, see if this helps. Read comments within code.
SQL> with test (id, id1, id2) as
2 -- result produced by current query
3 (select 1, 123, null from dual union all
4 select 1, 234, null from dual union all
5 select 1, 456, null from dual union all
6 select 1, null, '789' from dual union all
7 select 1, null, '012' from dual
8 ),
9 taba as
10 -- ID1 and row ordinal number (for joining purposes)
11 (select id, id1, row_number() over (order by id1) rn
12 from test
13 ),
14 tabb as
15 -- ID2 and row ordinal number (for joining purposes)
16 (select id, id2, row_number() over (order by id2) rn
17 from test
18 )
19 -- join them on ID and RN
20 select a.id, a.id1, b.id2
21 from taba a join tabb b on a.id = b.id and a.rn = b.rn
22 where a.id1 is not null
23 order by a.id, a.id1, b.id2;
ID ID1 ID2
---------- ---------- ---
1 123 012
1 234 789
1 456
SQL>

SELECT ID, ID1, ID2
FROM table1
WHERE ID1 IS NOT NULL

I think that you can use case statement.
look here: Multiple conditions with CASE statements
If after that you question continue, don't worry, call me.

Related

When single row not null then return nothing with Oracle SQL

When querying a table in Oracle Dev I need to ignore any ID that doesn't have a null date.
An ID can be returned multiple times e.g. 5 times, 4 can have a null date but one might have 01.01.2022 in which case all of them need to be ignored.
Here is the SQL:
SELECT
ID,
ACTIVATION_DATE,
ACCEPTED_DATE
FROM TABLE
WHERE ACCEPTED_DATE IS NOT NULL
--AND ACTIVATION_DATE IS NULL
AND ID IN ('AA1','AA2');
And the result:
ID
ACTIVATION_DATE
ACCEPTED_DATE
AA1
01/04/2022
AA1
15/03/2022
AA1
22/08/2022
07/06/2022
AA1
11/05/2022
AA2
06/06/2022
AA2
25/09/2022
12/12/2021
You can see AA1 has pulled 4 rows but because it has one activation date, they now all need to be ignored. If I leave AND ACTIVATION_DATE IS NULL in there it will still return the blank rows, which need to be ignored altogether.
Assume this will need to be a subquery? Any help would be much appreciated!
I have tried the SQL query as above
Use the COUNT analytic function:
SELECT id,
activation_date,
accepted_date
FROM (
SELECT id,
activation_date,
accepted_date,
COUNT(activation_date) OVER (PARTITION BY id) AS num_active
FROM table_name
WHERE accepted_date IS NOT NULL
AND id IN ('AA1','AA2')
)
WHERE num_active = 0;
I'd try with not exists:
Sample data:
SQL> WITH
2 table1 (id, activation_date, accepted_date)
3 AS
4 (SELECT 'AA1', NULL , DATE '2022-04-01' FROM DUAL UNION ALL
5 SELECT 'AA1', NULL , DATE '2022-03-15' FROM DUAL UNION ALL
6 SELECT 'AA1', DATE '2022-08-22', DATE '2022-06-07' FROM DUAL UNION ALL
7 SELECT 'AA2', DATE '2022-09-25', DATE '2021-12-12' FROM DUAL)
Query begins here:
8 SELECT id, activation_date, accepted_date
9 FROM table1 a
10 WHERE id IN ('AA1', 'AA2')
11 AND NOT EXISTS
12 (SELECT NULL
13 FROM table1 b
14 WHERE b.id = a.id
15 AND b.activation_date IS NULL);
ID ACTIVATION ACCEPTED_D
--- ---------- ----------
AA2 25/09/2022 12/12/2021
SQL>
AA1 is excluded from result as it contains NULL values in activation_date. AA2 is being returned as its activation_date isn't empty.

How can I select a data from another column from rows that have been selected?

I tried my best to figure and google this out, but couldn't really find a solid answer to it.
The problem I'm facing is that
Table 1:
ID Value 1
1 a
2 b
3 c
Table 2:
ID Value 2
1 4a
3 5b
4 6c
and I'd basically have to select the value from Table 1 that doesn't exist on Table 2 (Thus, 'b')
I can select and identify the ID that I want by using minus function between the tables, but can't seem to figure out a way to call a query to instead call the data.
Use the MINUS as a subquery (i.e. an inline view) (lines #14 - 16):
Sample data:
SQL> with
2 table1(id, value1) as
3 (select 1, 'a' from dual union all
4 select 2, 'b' from dual union all
5 select 3, 'c' from dual
6 ),
7 table2 (id, value2) as
8 (select 1, '4a' from dual union all
9 select 3, '5b' from dual union all
10 select 4, '6c' from dual
11 )
Query begins here:
12 select a.*
13 from table1 a
14 where a.id in (select t1.id from table1 t1
15 minus
16 select t2.id from table2 t2
17 );
ID VALUE1
---------- ----------
2 b
SQL>
Alternatively, use not exists:
<snip>
12 select a.*
13 from table1 a
14 where not exists (select null
15 from table2 b
16 where b.id = a.id
17 );
ID VALUE1
---------- ----------
2 b
SQL>

How to combine 2 tables with hard constraint

I got a hard problem in sql that I can't resolve.
I show you it now:
table1
id id2 enter_date exit_date type
1 5 05/05/2021 11/05/2021 A
1 5 11/05/2021 20/05/2021 B
1 . 20/05/2021 30/05/2021 .
table2
id id2 enter_date exit_date type
1 5 08/05/2021 14/05/2021 A
1 5 14/05/2021 20/05/2021 B
1 5 20/05/2021 30/05/2021 C
My table 1 contains all good values but the problem is that she got missing value ( . ) and in my table2, I have every values. But all the values of table2 which are ever in the table 1 are false. But every value of table2 witch are not ever in table 1 are good.
So with my example, it gives me it :
table_final
id id2 enter_date exit_date type
1 5 05/05/2021 11/05/2021 A
1 5 11/05/2021 20/05/2021 B
1 5 20/05/2021 30/05/2021 C
SO I have good date, good type and no missing value.
I tried some thing with union all ... but nothing work.
Thanks for reading me !
This is how I understood the question. Read comments within code
SQL> with
2 -- sample data
3 table1 (id, id2, enter_date, exit_Date, type) as
4 (select 1, 5 , date '2021-05-05', date '2021-05-11', 'A' from dual union all
5 select 1, 5 , date '2021-05-11', date '2021-05-20', 'B' from dual union all
6 select 1, null, date '2021-05-20', date '2021-05-30', null from dual
7 ),
8 table2 (id, id2, enter_date, exit_Date, type) as
9 (select 1, 5 , date '2021-05-08', date '2021-05-14', 'A' from dual union all
10 select 1, 5 , date '2021-05-14', date '2021-05-20', 'B' from dual union all
11 select 1, 5 , date '2021-05-20', date '2021-05-30', 'C' from dual
12 )
13 -- query that returns result you need
14 -- Remove "invalid" rows from TABLE1 (the ones whose ID2 and TYPE aren't null
15 -- (or equal to dot, as you put it)
16 select *
17 from table1
18 where id2 is not null
19 and type is not null
20 union
21 -- From TABLE2, take rows that don't exist in TABLE1 already (matched by ID, ID2 and TYPE)
22 -- where ID2 and TYPE aren't NULL (in TABLE1).
23 select *
24 from table2
25 where (id, id2, type) not in (select id, id2, type
26 from table1
27 where id2 is not null
28 and type is not null
29 );
ID ID2 ENTER_DATE EXIT_DATE T
---------- ---------- ---------- ---------- -
1 5 05/05/2021 11/05/2021 A
1 5 11/05/2021 20/05/2021 B
1 5 20/05/2021 30/05/2021 C
SQL>

How do I need to change my sql to get what I want in this case?

I have a table like following:
id value date
1 5 2015-01-10
2 5 2015-06-13
3 5 2015-09-05
4 11 2015-02-11
5 11 2015-01-10
6 11 2015-01-25
As can be seen, every value appears 3 times with different date. I want to write a query that returns the unique values that has the maximum date, which would be the following for the above table:
id value date
3 5 2015-09-05
4 11 2015-02-11
How could I do it?
This is the updated question:
The real question I am encountering is a little bit more complicated than the simplified version above. I thought I can move a step further once I know the answer to the simplified version, but I guest I was wrong. So, I am updating the question herein.
I have 2 tables like following:
Table 1
id id2 date
1 2 2015-01-10
2 5 2015-06-13
3 9 2015-09-05
4 10 2015-02-11
5 26 2015-01-10
6 65 2015-01-25
Table 2
id id2 data
1 2 A
2 5 A
3 9 A
4 10 B
5 26 B
6 65 B
Here, Table 1 and Table 2 are joined by id2
What I want to get is two records as follows:
id2 date data
9 2015-01-10 A
10 2015-02-11 B
You can use row_number to select the rows with the greatest date per value
select * from (
select t2.id2, t1.date, t2.data,
row_number() over (partition by t2.data order by t1.date desc) rn
from table1 t1
join table2 t2 on t1.id = t2.id2
) t where rn = 1
select a.id, a.value, a.date
from mytable a,
( select id, max(date) maxdate
from mytable b
group by id) b
where a.id = b.id
and a.date = b.maxdate;
Oracle Setup:
CREATE TABLE Table1 ( id, id2, "date" ) AS
SELECT 1, 2, DATE '2015-01-10' FROM DUAL UNION ALL
SELECT 2, 5, DATE '2015-06-13' FROM DUAL UNION ALL
SELECT 3, 9, DATE '2015-09-05' FROM DUAL UNION ALL
SELECT 4, 10, DATE '2015-02-11' FROM DUAL UNION ALL
SELECT 5, 26, DATE '2015-01-10' FROM DUAL UNION ALL
SELECT 6, 65, DATE '2015-01-25' FROM DUAL;
CREATE TABLE Table2 ( id, id2, data ) AS
SELECT 1, 2, 'A' FROM DUAL UNION ALL
SELECT 2, 5, 'A' FROM DUAL UNION ALL
SELECT 3, 9, 'A' FROM DUAL UNION ALL
SELECT 4, 10, 'B' FROM DUAL UNION ALL
SELECT 5, 26, 'B' FROM DUAL UNION ALL
SELECT 6, 65, 'B' FROM DUAL;
Query:
SELECT MAX( t1.id ) KEEP ( DENSE_RANK LAST ORDER BY t1."date" ) AS id,
MAX( t1.id2 ) KEEP ( DENSE_RANK LAST ORDER BY t1."date" ) AS id2,
MAX( t1."date" ) AS "date",
t2.data
FROM Table1 t1
INNER JOIN
Table2 t2
ON ( t1.id = t2.id AND t1.id2 = t2.id2 )
GROUP BY t2.data
Output:
ID ID2 date DATA
---------- ---------- ------------------- ----
3 9 2015-09-05 00:00:00 A
4 10 2015-02-11 00:00:00 B
Query 2:
SELECT id,
id2,
"date",
data
FROM (
SELECT t1.*,
t2.data,
ROW_NUMBER() OVER ( PARTITION BY t2.data ORDER BY t1."date" DESC ) AS rn
FROM Table1 t1
INNER JOIN
Table2 t2
ON ( t1.id = t2.id AND t1.id2 = t2.id2 )
)
WHERE rn = 1;
Output:
ID ID2 date DATA
---------- ---------- ------------------- ----
3 9 2015-09-05 00:00:00 A
4 10 2015-02-11 00:00:00 B

Replace duplicate values only in consecutive records with NULL [duplicate]

This question already has an answer here:
shows blanks for repeating values in a result set
(1 answer)
Closed 4 years ago.
Say I have two tables
Tran (Tran_Id, Tran_Name)
TFlag(Tran_Id, Flag)
My Query Result is Like:
TRAN_ID TRAN_NAME FLAG
-------------------------
101 Lend A
101 Lend B
101 Lend C
101 Lend D
102 Borrow E
101 Lend F
101 Lend G
I want the output to be like this:
TRAN_ID TRAN_NAME FLAG
-------------------------
101 Lend A
(null) (null) B
(null) (null) C
(null) (null) D
102 Borrow E
101 Lend F
(null) (null) G
You could use analytic LAG() OVER().
SQL Fiddle for a working demo.
For example,
SQL> SELECT
2 CASE
3 WHEN lag(tran_id) over(order by NULL) = tran_id
4 THEN NULL
5 ELSE tran_id
6 END tran_id,
7 CASE
8 WHEN lag(tran_name) over(order by NULL) = tran_name
9 THEN NULL
10 ELSE tran_name
11 END tran_name,
12 flag
13 FROM t;
TRAN_ID TRAN_N F
---------- ------ -
101 Lend A
B
C
D
102 Borrow E
101 Lend F
G
7 rows selected.
In both SQL Server and Oracle you can use LAG analytic function. Oracle:
WITH data (tran_id, tran_name, flag) AS (
SELECT 01, 'Lend', 'A' FROM DUAL UNION ALL
SELECT 101, 'Lend', 'B' FROM DUAL UNION ALL
SELECT 101, 'Lend', 'C' FROM DUAL UNION ALL
SELECT 101, 'Lend', 'D' FROM DUAL UNION ALL
SELECT 102, 'Borrow', 'E' FROM DUAL UNION ALL
SELECT 101, 'Lend', 'F' FROM DUAL UNION ALL
SELECT 101, 'Lend', 'G' FROM DUAL
)
SELECT
NVL2(keep, tran_id, null) tran_id,
NVL2(keep, tran_name, null) tran_name,
flag
FROM (
SELECT
tran_id, tran_name, flag,
CASE WHEN LAG(tran_id) OVER (ORDER BY flag) <> tran_id OR LAG(tran_name) OVER (ORDER BY flag) <> tran_name THEN 1 END keep
FROM
data)