Oracle SQL - implement logic based on CASE expression result - sql

I have following query which returns me of percentage of rows with at least one NULL in any of columns:
SELECT
(SUM(CASE WHEN tablea.test IS NULL OR tableb.test IS NULL THEN 1 ELSE NULL END)/7000)*100) "at least one NULL (%)"
FROM tablea
FULL OUTER JOIN tableb
ON
tablea.test = tableb.test
WHERE ROWNUM < 7000;
Query works fine to me and I am getting valid result.
But I need to do further action in tablec, based on percentage calculated in my SELECT statement. If percentage of rows with NULL is below 30% I need to insert "YES" string inside table "tablec" column "resultcol", how can I implement such a logic?
Is it for example possible to store SELECT statement result in some temporary variable which will be used in another SQL query?

You can use:
INSERT INTO tablec (resultcol)
SELECT 'YES'
FROM tablea
FULL OUTER JOIN tableb
ON tablea.test = tableb.test
WHERE ROWNUM < 7000
HAVING COUNT(CASE WHEN tablea.test IS NULL OR tableb.test IS NULL THEN 1 END)
< COUNT(*) * 0.3;
db<>fiddle here
Update:
If you want to insert a row if it does not exist or change the row if it does exist then:
MERGE INTO tablec dst
USING (
SELECT CASE
WHEN EXISTS (
SELECT 1
FROM tablea
FULL OUTER JOIN tableb
ON tablea.test = tableb.test
WHERE ROWNUM < 7000
HAVING COUNT(CASE WHEN tablea.test IS NULL OR tableb.test IS NULL THEN 1 END)
< COUNT(*) * 0.3
)
THEN 'YES'
ELSE 'NO'
END AS resultcol
FROM DUAL
) src
ON (1 = 1)
WHEN NOT MATCHED THEN
INSERT (resultcol) VALUES (src.resultcol)
WHEN MATCHED THEN
UPDATE SET resultcol = src.resultcol;
Or, to just update it:
UPDATE tablec
SET resultcol = CASE
WHEN EXISTS (
SELECT 1
FROM tablea
FULL OUTER JOIN tableb
ON tablea.test = tableb.test
WHERE ROWNUM < 7000
HAVING COUNT(
CASE
WHEN tablea.test IS NULL
OR tableb.test IS NULL
THEN 1
END
) < COUNT(*) * 0.3
)
THEN 'YES'
ELSE 'NO'
END;
db<>fiddle here

Related

SQL AND to see if two flags are set in two different tables?

SELECT 1 FROM
(SELECT 1 FROM mytable1 WHERE parentid = 'ID1' AND flag = 'Y') as X,
(SELECT 1 FROM mytable2 WHERE id = 'ID2' AND flag = 'Y') as Y
I'm making a query to see if two flags are set in two tables, where 'parentid' and 'id' are both primary keys. The query should return a row only if both flags are set to 'Y', or return nothing otherwise, then I do stuff with that result in my backend code.
I've tested this and it works but I feel like it looks wonky and could be optimized. Any ideas?
To get what You want:
SELECT 1
FROM mytable1 AS a, mytable2 AS b
WHERE a.parentid = 'ID1' AND a.flag = 'Y'
AND b.id = 'ID2' AND b.flag = 'Y'
But in fact, I would prefer a query with LEFT JOIN, which always gives one row, like this:
SELECT CASE WHEN a.flag = 'Y' AND b.flag = 'Y' THEN 1 ELSE 0 END AS result
FROM TABLE ( VALUES 1 ) AS always(present)
LEFT JOIN mytable1 AS a ON a.parentid = 'ID1'
LEFT JOIN mytable2 AS b ON b.id = 'ID2'
Your query is fine (although I would use CROSS JOIN. However, I would prefer a row with a specific value. I would phrase that as:
SELECT (CASE WHEN EXISTS (SELECT 1 FROM mytable1 WHERE parentid = 'ID1' AND flag = 'Y') AND
EXISTS (SELECT 1 FROM mytable2 WHERE id = 'ID2' AND flag = 'Y')
THEN 1 ELSE 0
END) as flag
You may need from dual, depending on your database.
It better to use JOIN instead of doing subqueries
SELECT mytable1.parentid, mytable2.id
FROM mytable1
JOIN mytable2 ON mytable2.flag = "Y" AND mytable1.flag = "Y"

Is it possible to do a Select statement within a Case statement

Is something like this possible?
SELECT WH_ACC_NO,
CASE
WHEN FIELD2 IN (SELECT * FROM TABLEB)
THEN 'PASS'
ELSE 'FAIL'
END
FROM TABLEA
FIELD2 should be mapped with TABLEB then you can do :
SELECT ta.WH_ACC_NO,
(CASE WHEN tb.FIELD2 IS NOT NULL
THEN 'PASS'
ELSE 'FAIL'
END)
FROM TABLEA ta LEFT OUTER JOIN
TABLEB tb
ON tb.FIELD2 = ta.FIELD2;
I have used FIELD2 with TABLEB, you can correct the ON clause with correct column name.
The syntax for a SELECT within CASE is a bit limited in Teradata, you need to write a Correlated Scalar Subquery to avoid the 3771 Illegal expression in WHEN clause of CASE expression error:
SELECT WH_ACC_NO,
CASE -- when FieldWhatever is not unique this shuld be MAX(FieldWhatever)
WHEN FIELD2 = (SELECT FieldWhatever FROM TABLEB AS b WHERE a.Field2 = b.FieldWhatever)
THEN 'PASS'
ELSE 'FAIL'
END
FROM TABLEA AS a
This does work normally. Code in the example below.
declare #t1 table (num int)
insert into #t1 select 1
insert into #t1 select 2
declare #t2 table (value nvarchar(10), broj int)
insert into #t2 select 'test1', 1
insert into #t2 select 'test2', 3
select case when broj in (select num from #t1) then 'good' else 'bad' end
from #t2
Yes, you can.
I tested this using the following:
select top 50 ID, Name, DOB
into #Population
from Table1
select CASE
when ID in (select ID from #Population)
then 1
else 0
end as Number
from #Population
I am sure there are limitations but this should answer your question.
Good Luck!
One thing you should know that you can't type the * in the inner query because it will return more than one result.so here is the solution.
SELECT ta.WH_ACC_NO,
(CASE WHEN tb.FIELD2 IS NOT NULL
THEN 'PASS'
ELSE 'FAIL'
END)
FROM TABLEA ta JOIN
TABLEB tb
ON tb.FIELD2 = ta.FIELD2;

How to return true if two same columns in two different tables have values? SQL

Back on here with another question for y'all!
So we have two Pivot tables, Table_A and Table_B. Both tables have the same columns.
I was trying to write a query that'll go through each row and return true ONLY AND ONLY IF the record with the same ID has a value in the 'Value' field.
So for example, Table_A has 'sdnbfsj' value for record ID3 and Table_B has a value under the 'Value' field for the same record ID.
The query should be able to validate that the same cell in both tables have values and if they do, then return true. If the tables only had three records in total, this would have returned true but notice that record ID 5 has a value in Table_A but record ID 5 is NULL in Table_B. SO the query should return false.
This is what I have so far:
SELECT source_column from
(
select source_column from Table_A WHERE Value_Inserted=1
EXCEPT
select source_column from Table_B WHERE Value_Inserted=1
)X
WHERE source_column IN
(
'Col_1'
,'COl_2'
,'Col_3'
,'Col_4'
)
You should be able to do this by first Joining the two tables on id and then counting based on your condition. Then... return "true" or "false"
SELECT CASE WHEN SUM(CASE WHEN t1.value IS NOT NULL AND t2.value IS NOT NULL THEN 1 ELSE 0 END) = Count(*) THEN 'True' ELSE 'False' END as test
FROM table_a as t1
INNER JOIN table_b as t2 ON
t1.id = t2.id
Syntax may differ depending on what RDBMS you use.
I think you want:
select min(case when a.value is not null and a.value is null then 0
when a.value is null a and a.value is not null then 0
else 1
end) as flag
from a join
b
on a.class = b.class and a.source_col = b.source_col;
This treats 1 as true and 0 as false.
Depends on the DBMS that you're using ;
For Oracle use nvl2 function :
select nvl2(a.value, 1, 0) * nvl2(b.value, 1, 0)
from Table_A a
inner join Table_B b
on (a.ID = b.ID);
For MSSQL convert or cast functions might be used :
select convert(int, ( case when IsNull(a.value,'0') = '0' then '0'
else '1'
end ))
*
convert(int, ( case when IsNull(b.value,'0') = '0' then '0'
else '1'
end )) as result
from Table_A a
inner join Table_B b
on (a.ID = b.ID);
For MySQL use IfNull function :
select ( case when IfNull(a.value,'0') = '0' then '0'
else '1'
end )
*
( case when IfNull(b.value,'0') = '0' then '0'
else '1'
end ) as result
from Table_A a
inner join Table_B b
on (a.ID = b.ID);
For PostGreSQL use coalesce function :
select cast( ( case when coalesce(a.value,'0') = '0' then '0'
else '1'
end ) as int )
*
cast( ( case when coalesce(b.value,'0') = '0' then '0'
else '1'
end ) as int ) as result
from Table_A a
inner join Table_B b
on (a.ID = b.ID);
All of them give the following results
result
0
0
1
0
0

SQL JOIN WITH TWO WHERE CLAUSES

I would like to implement the following SQL query : suppose using JOIN clause, due to now it's running quite slow:
SELECT ID_USER, NICK
FROM TABLE1
WHERE ID_USER IN
(
SELECT ID_INDEX1
FROM TABLE2
WHERE ID_INDEX2 = '2'
)
AND ID_USER NOT IN
(
SELECT ID_INDEX2
FROM TABLE2
WHERE ID_INDEX1 = '2' AND GO ='NO'
)
ORDER BY NICK ASC
You could do the "including" part with INNER JOIN and the "excluding" part with a "LEFT JOIN" + filtering:
SELECT DISTINCT t1.ID_USER, t1.NICK
FROM TABLE1 t1
INNER JOIN TABLE2 t2IN
ON t1.ID_USER = t2IN.ID_INDEX1
AND t2IN.ID_INDEX2 = '2'
LEFT JOIN TABLE2 t2OUT
ON t1.ID_USER = t2OUT.ID_INDEX2
AND t2OUT.ID_INDEX1 = '2'
AND t2OUT.GO = 'NO'
WHERE t2OUT.ID_INDEX IS NULL
ORDER BY t1.NICK ASC
Assuming that you want to filter by ID_INDEX1 in both cases (see my comment on your question), you can:
count the number of rows per user in table2 with value = 2
count the number of rows per user in table2 with value = 2 and go = 'NO'
return only those for which the first count is greater than 0 and the second count equals 0
i.e.:
select * from (
select
id_user,
nick,
sum(case when table2.id_index2 = '2' then 1 else 0 end) as count2_overall,
sum(case when table2.id_index2 = '2' and go = 'NO' then 1 else 0 end) as count2_no
from table1
join table2 on table1.id_user = table2.id_index1
group by id_user, nick
)
where count2_overall > 0 and count2_no = 0

oracle sql error Case When Then Else

SELECT *
FROM FirstTable
WHERE RowProcessed = 'N'
AND (
CASE
WHEN EXISTS(SELECT top 1 FROM SecondTable)
THEN 1
ELSE EXISTS(
SELECT SecondTable.RowProcessed
FROM SecondTable
WHERE FirstTable.Key = SecondTable.Key
AND SecondTable.RowProcessed = 'Y'
)
END
)
AND OtherConditions
Case When then else in where clause. Not sure about the syntax.
I would like to verify there are rows in the SecondTable and if there are rows check for another condition, that is basicallly what I want to do.
Perhaps this is what you want? If there are rows in SecondTable, then do the second EXISTS:
SELECT * FROM FirstTable
WHERE RowProcessed = 'N'
AND (NOT EXISTS (SELECT 1 from SecondTable)
OR EXISTS (SELECT 1 FROM SecondTable
WHERE FirstTable.Key = SecondTable.Key
and SecondTable.RowProcessed = 'Y'))
AND OtherConditions