Oracle select query with dynamic in clause - sql

I have the following query
select * from table_1
where Conditions in
(select case when check_condition = 'Y' then 'Condition_1'
else 'N/A' end as Check_condition
from table_2
WHERE id = 1122)
where table_1 contains the values in column Conditions as follows.
Condition_1,Condition_2
This works fine and return me the results.
i want to use multiple select statements inside the in clause and I did it as below.
select * from table_1
where Conditions in (
select ''''||
(select case when check_condition = 'Y' then 'Condition_1'
else 'N/A' end as Check_condition
from table_2
WHERE id = 1122)||''''||','''||
(select case when check_condition = 'Y' then 'Condition_2'
else 'N/A' end as Check_condition
from table_2 WHERE id = 1122)||''''
from dual
)
inner query ( inside the in clause) giving me the correct results as expected -
'Condition_1','Condition_2'
and when I copy paste it to the parent query it works fine and show the results.
select * from table_1 where Conditions in ('Condition_1','Condition_2')
My issue is, it is not giving any results when I used the second query. I know that sub query will return the results that should match the rows in the outer query. But it shows me empty result set.
I am using oracle 11g
Can anyone please help me out.. Thank you all in advance.

The question is a bit unclear regarding requirements. What I think you want is to select records from table1 only when:
rows match 'Condition_1' or 'Condition_2'
check_condition = 'Y'
there is a row in table2 with an ID = 1122
It's not clear from your question whether check_condition is a column or a variable, and if it is a column to which table it belongs. Consequently this solution may be wrong but it illustrates the principle.
select * from table1 t1
where t1.conditions in ('Condition_1','Condition_2')
and t1.check_condition = 'Y'
and exists
( select null from table2 t2
where t2.id = 1122 )
If this doesn't provide the solution you need please revise your question so it states the business logic you need to implement, and also includes relevant tables descriptions.

You aren't ending up with two values passed into the in clause like when you do it manually:
select * from table_1 where Conditions in ('Condition_1','Condition_2')
You're passing a single value which is the concatenation of the values:
select * from table_1 where Conditions in ('''Condition_1'',''Condition_2''')
And no condition matches that concatenated value, so you get no results. You could do something like:
select * from table_1 where Conditions in (
select case when check_condition = 'Y' then 'Condition_1' else 'N/A' end
from table_2 WHERE id = 1122
union all
select case when check_condition = 'Y' then 'Condition_2' else 'N/A' end
from table_2 WHERE id = 1122
)
Or possibly, if I follow what you're doing (which is doubtful as I'm not sure I understand your data model!):
select * from table_1 where check_condition != 'Y' or Conditions in (
select 'Condition_1' from table_2 WHERE id = 1122
union all
select 'Condition_2' from table_2 WHERE id = 1122
)
It seems like you should be able to do this more cleanly, with joins, but I think we'd need to see the structures and sample data to understand what's going on a bit more.

Related

Two Table Comparison in HIVE

I have two different set of tables. I want to compare the total count in both tables and want to display whether the two tables counts are matching or not. If matching, then 'Pass' else 'fail'.
SELECT (SELECT COUNT (*)
FROM Table1 t1
INNER JOIN Table2 t2
ON TRIM (t1.mgac_ac_id) = TRIM (t2.account))
AS cnt1,
(SELECT COUNT (*) FROM t3) AS cnt2 where cnt1=cnt2;
Above show code is incorrect. Could anyone help on code. Whether want to create any variables in HIVE?
OK, it's simple to complete this. like below:
select
case when tmp1.value = tmp2.value then 'Pass' else 'Fail' end as result
from
(select count(1) as value from table1) tmp1
join
(select count(1) as value from table2) tmp2 on 1=1

How to set SQL condition precedence for two different conditions

I'm having two different tables 'TABLE1' and 'TABLE2'. Both of these tables have same column name - 'IS_PDF'.
RE TABLE1.IS_PDF value, I retrieved the required details using select statement where I added where clause like below.
select * from TABLE1 where TABLE1.IS_PDF = 'Y';
Similarly, I can get the values for TABLE2 as well where TABLE2.IS_PDF = 'Y'
Now, my task is to have one select statement to get the details from both tables 'TABLE1' and 'TABLE2' by setting a precedence on below condition # 1.
If TABLE1.IS_PDF = 'Y', return records matching same condition.
If TABLE1.IS_PDF = 'N' but TABLE2.IS_PDF = 'Y' then return records matching same condition.
If both have IS_PDF = 'N', return nothing.
I used below Select statement but getting Above conditions # 1 and 2 at the same time only.
select * from TABLE1, TABLE2
where
(TABLE1.IS_PDF = 'Y') or (TABLE2.IS_PDF = 'Y' and TABLE1.IS_PDF = 'N' )
Please guide on the same.
Thanks
You seem to want something like this:
select t1.*
from table1 t1
where t1.is_pdf = 'Y'
union all
select t2.*
from table2 t2
where t2.is_pdf = 'Y' and
not exists (select 1 from table1 t1 where t1.is_pdf = 'Y' and t1.?? = t2.??);
The ?? represents the column(s) used for matching between the two tables.
Thanks for the quick response.
Sample code-
select TABLE1.IS_PDF, TABLE2.IS_PDF, TABLE1.ID, TABLE1.GLOBAL_ID, TABLE1.title,
from TABLE1, TABLE2
where TABLE1.USER_ID = 82340
and TABLE1.NAME = 'INDIA'
and (TABLE1.IS_PDF = 'Y') or (TABLE2.IS_PDF = 'Y' and TABLE1.IS_PDF = 'N' )
I need to set a precedence on below condition # 1. If condition # 1 meets, it's fine. Otherwise go for #2 then #3.
If TABLE1.IS_PDF = 'Y', return records matching same condition.
If TABLE1.IS_PDF = 'N' but TABLE2.IS_PDF = 'Y' then return records matching same condition.
If both have IS_PDF = 'N', return nothing.

How to exclude a record from sql with specific value

I have a question about my sql query. I need to exclude all the rows that have the value 'f' in it.
I have tried doing
SELECT * FROM table WHERE type NOT IN ('f')
But this doesnt seem to be working. Any help would be appreciated
EDIT: sorry for being unclear,
The problem I have is that theres multiple rows like this
name type
test1 f
test1 l
If i would use this query it would still return me test1 but what I want is that it returns NULL. Can this be done?
You apparently want to see rows where no other rows for the same name has the value f
select t1.*
from the_table t1
where not exists (select *
from the_table t2
where t1.name = t2.name
and t2.type = 'f');
If no such row exists the query will not return null it will simply return no rows at all.
Use the HAVING clause :
SELECT s.name
FROM YourTable s
GROUP BY s.name
HAVING COUNT(CASE WHEN s.type = 'f' THEN 1 END) = 0

Compare all values from one table against a reference table and flag matches as '1' else '0'

I need to create a reference table that is easy to update - call it REF table.
Then I need to compare values from a column in a different table - call it OTHER table - against values in the REF table.
Then, ideally, use a CASE WHEN statement such that where values from OTHER match values from REF then 1 else 0.
I've searched online, including this site for a while now and can't find exactly what I need, there are answers where only matching values are returned but I need to return all values and flag correct one as 1 and incorrect as 0.
Maybe I'm not wording my search very well as I'm new to this.
Use a left join and a case? I assume that there is a field that can be joined
eg
select T1.ColA, case when T2.ColA is not null then 1 else 0 end as T2Match
from Table1 T1
left join Table2 T2
on T1.ColA = T2.ColA
or a case when exists
select T1.ColA,
case
when exists (select T2.ColA from Table2 where T1.ColA = T2.ColA) then 1
else 0 end as T2Match
from Table1 T1
If you are using SQL Server, use a corelated subquery.
SELECT OTHER.Column, ISNULL((select MAX(1) from REF WHERE REF.Column=OTHER.Column),0) ExistInRef
FROM OTHER

SQL Statement Performance Issue on Informix

I have this Informix SQL statement which takes ages to run. Does anybody see any way to optimize it so it wouldn't take so long?
SELECT * FROM OriginalTable WHERE type = 'S' AND flag <> 'S' INTO TEMP TempTableA;
SELECT * FROM OriginalTable WHERE type = 'Z' AND flag <> 'S' INTO TEMP TempTableB;
UPDATE OriginalTable SET flag = 'D' WHERE Serialnumber in
(
select Serialnumber from TempTableA
WHERE NOT EXISTS(SELECT * FROM TempTableB
WHERE TempTableB.Col1 = TempTableA.Col1
AND TempTableB.Col2 = TempTableA.Col2)
)
I have in my OriginalTable around 300 million rows, TempTableA 93K rows, and TempTableB 58K rows.
Update OriginalTable
Set flag = 'D'
Where Type = 'S'
And Flag <> 'S'
And Not Exists (
Select 1
From OriginalTable As T1
Where T1.Type = 'Z'
And T1.flag <> 'S'
And T1.Col1 = OriginalTable.Col1
And T1.Col2 = OriginalTable.Col2
)
In a similar approach as #tombom stated. Pre-query only the columns you care about to keep the temp table smaller. If you are dealing with a table of 60 columns, you are filling a whole lot more than just 3-4 columns where your primary consideration are valid serial numbers. Pre-test the query to make sure it gives you the correct set you are expecting, then apply that to your SQL-update.
So here, the inner query are the ones you DO NOT WANT... Since you were comparing against only column 1 and column 2 from this table, that's all I'm pre-querying. I'm then doing a LEFT JOIN to this inner result set on COL1 and COL2. I know, you want to EXCLUDE THOSE FOUND IN THIS result set... That's why, in the OUTER WHERE clause, I've added "AND ExcludeThese.Col1 IS NULL". So, any instances from OT1 that never existed in the subquery are good to go (via left join), and those that WERE FOUND, WILL have a match on col1 and col2, but THOSE will be excluded via the "and" clause I've described.
SELECT OT1.SerialNumber
FROM OriginalTable OT1
LEFT JOIN ( select OT2.Col1,
OT2.Col2
FROM OriginalTable OT2
where OT2.type = 'Z'
AND OT2.flag <> 'S' ) ExcludeThese
ON OT1.Col1 = ExcludeThese.Col1
AND OT1.Col2 = ExcludeThese.Col2
WHERE OT1.type = 'S'
AND OT1.flag <> 'S'
AND ExcludeThese.Col1 IS NULL
ORDER BY
OT1.SerialNumber
INTO
TEMP TempTableA;
Again, test this query by itself to make sure you ARE getting the records you expect. To help clarify the records returned, change the above select to include more columns for a mental / sanity check, such as
SELECT OT1.SerialNumber,
OT1.Col1,
OT1.Col2,
ExcludeThese.Col1 JoinedCol1,
ExcludeThese.Col2 JoinedCol2
from <keep rest of query intact>
Now, you'll be able to see the serial number and instances of those columns that would or not be joined to the "excludeThese" resultset... Try again, but remove only the
"AND ExcludeThese.Col1 IS NULL" clause, and you'll see the other lines and WHY they are being excluded -- that is if you DID have any questions to the content.
Once you are satisfied with the pre-query... which will only return the single column of SerialNumber, that can be index/optimized since you are pulling into a temp table, build an index, then apply your update.
UPDATE OriginalTable
SET flag = 'D'
WHERE Serialnumber in ( select Serialnumber from TempTableA );
I was too lazy to test with test data, but maybe this can do?
SELECT col1, col2,
CASE WHEN type = 'S' THEN 1
ELSE WHEN type = 'Z' THEN 2 END AS filteredType
FROM OriginalTable WHERE (type = 'S' OR type = 'Z') AND flag <> 'S' INTO TempTable;
UPDATE OriginalTable SET flag = 'D' WHERE Serialnumber IN
(
SELECT t1.Serialnumber FROM TempTable t1
LEFT JOIN TempTable t2 ON (t1.col1 = t2.col2 AND t1.col2 = t2.col2)
WHERE t1.filteredType = 1
AND t2.filteredType = 2
AND t2.Serialnumber IS NULL
)
That way you can omit one loading into temp table. On the other hand there will be no index on the new column filteredType.
Also I have no idea of informix. Hope it helps anyway.