selecting only NON NULL values in Oracle sql table - sql

I have a table that has 40 columns/headers and 15 rows(may vary due to the high volume records); In the records/data, many columns which have NULL values or in other words, these columns were not in a production environment, so no validation required or to list in the output.
I wanna list only the NON NULL values(Column vise) in the select table even if the entire Column is NULL.
COLUMNS
Col_A
Col_B
Col_C
Col_D
Col_E
Col_F
ROW1
Val_1
Val_2
NULL
Val_4
Val_5
Val_6
ROW2
Val_1
Val_2
NULL
Val_4
Val_5
NULL
Here I want to list all the columns except "Column C" which is NULL

In sql this is not possible, because that is not how a sql query works. In short this is what happens
You tell the database engine what columns you want to get back and what the conditions are (conditions filter rows, not columns). At this point the database does not know anything about the results. This is done using the query syntax.
The db engine runs the query and returns the result, row by row. The db engine does not know what is in those rows/columns.
The requirement is to skip columns that have no data. As explained above, that is not know at the time of running the query, but you could work around this, for example by creating a view that only has the columns with data. Bear in mind that this means that every query has to run at least once before the query itself, which could be a downside if you're talking about large datasets.
Lets create a sample table
CREATE TABLE tab1 (c1, c2, c3, c4) AS
(
SELECT 1,CAST(NULL AS NUMBER), 2,4 FROM DUAL UNION ALL
SELECT NULL,NULL, 1,3 FROM DUAL UNION ALL
SELECT 1,NULL, NULL,3 FROM DUAL UNION ALL
SELECT 1,NULL, 2,NULL FROM DUAL UNION ALL
SELECT 4,NULL, 3,4 FROM DUAL
);
Now it's not possible to know which columns have only NULL values before we run the query, but we can run a query to know which columns have only NULL values using an aggregate function like MAX, MIN OR SUM. Lets call this QUERY1. For example:
SELECT MAX(c1),MAX(c2),MAX(c3),MAX(c4) FROM tab1;
MAX(C1) MAX(C2) MAX(C3) MAX(C4)
---------- ---------- ---------- ----------
4 3 4
Now we can convert that select so it generates another select that that only selects the columns with not null values. Lets call this QUERY2.
SELECT
'SELECT '||
RTRIM(
NVL2(SUM(c1),'c1,','') ||
NVL2(SUM(c2),'c2,','') ||
NVL2(SUM(c3),'c3,','') ||
NVL2(SUM(c4),'c4,','')
,',')||' FROM tab1;' FROM tab1;
STMT
---------------------------------------------------------------
CREATE OR REPLACE VIEW tab1_v AS SELECT c1,c3,c4 FROM tab1;
There you go - this statement will only return the columns that have no NULL values. Note that this is not foolproof. If a row is created or updated after you run QUERY1 but before you run QUERY2 that would alter the results of QUERY1, it could not select the correct columns.

Related

How to check/select if a string contains value from a table column values?

Lets say I have this number 123456789 and I have a table column which have different values numbers like:
TABLE_COLUMN
123
456
555
763
Is there a way to do something like SELECT * FROM TABLE WHERE 123456789 CONTAINS (values from that table column).
Are you looking for this?
select t.*
from table t
where cast(123456789 as varchar2(255)) like '%' || cast(table_column as varchar2(255)) || '%';
The explicit casts are not necessary, but I'm not a fan of implicit type conversion.
How about INSTR?
SQL> with test (tc) as
2 (select '123' from dual union all
3 select '456' from dual union all
4 select '555' from dual union all
5 select '763' from dual
6 )
7 select *
8 from test
9 where instr('123456789', tc) > 0;
TC
---
123
456
SQL>
You show some pseudo-code, but I doubt that's what you want to do. You show "select * from table where..." - is the string 123456789 in the same table where you have the column against which you must check? That sounds odd.
Rather, I imagine you have a table with a column of values against which you must test, and an "input" value (either a single one or perhaps values in ANOTHER table), and you must test that input value against ALL the values (in ALL rows) in the "test" table.
If so, you probably want something like this... I show the input as a bind variable, but you can change this easily for other uses.
select <whatever>
from <wherever>
where exists (select * from <table> where instr(:input_string, table_column) > 0)
If the inputs (or the values stored in that column) are numbers instead of strings, you can convert to strings using TO_CHAR().

Column Mismatch in UNION queries

I have columns A,B in Table 1 and columns B,C in Table 2.Need to perform Union between them .
For example : select A,B from Table 1 UNION select 0,B from Table 2.
I dont need this zero to solve the column mismatch.Instead is there any other solution?
Am asking the question by providing simple example . But in my case the table structure is very large and the queries are already built.Now I need to fix this union query by replacing this zero.(due to DB2 upgrade)
Can anyone help?
For two legs A and B in a union to be union compatible it is required that:
a) A and B have the same number of columns
b) The types for each column in A is compatible with the corresponding column in B
In your query you can use null that is part of every type:
select a, b from T1
UNION
select null, b from T2
Under certain circumstances, you may have to explicitly cast null to the same type as A has (probably not in this case):
select a, b from Table 1
UNION
select cast(null as ...), b from Table 2
A column returned in a SQL result set can only have one data type.
A union or union all results in rows from the first query and the rows of the second query (in case of union they are deduplicated).
So the first column of the first query needs to match the data type of the first column of the second query.
You can check this by running a describe:
describe select a,b from t1
If you work within a GUI (JDBC Connection) you could also use
call admin_cmd('describe select a,b from t1')
So if the some column does not match you have to explicitly cast the data types.

While inserting multiple rows what does the statement 'select 1 from dual' do?

While inserting multiple rows into a table using the following style :
insert all
into ghazal_current (GhazalName,Rating) values('Ajab Apna Haal Hota Jo Visaal-e-Yaar Hota',5)
into ghazal_current (GhazalName,Rating) values('Apne Hothon Par Sajana Chahta Hun',4)
into ghazal_current (GhazalName,Rating) values('Shaam Se Aankh Mein Nami Si Hai',4)
into ghazal_current (GhazalName,Rating) values('Tumhe Yaad Ho Ke Na Yaad Ho',3)
select 1 from dual;
What does the statement select 1 from dual mean ? What is it here for ?
DUAL is a built-in table, useful because it is guaranteed to return only one row. This means DUAL may be used to get pseudo-columns such as user or sysdate, the results of calculations and the like. The owner of DUAL is SYS but it can be accessed by every user. DUAL is well-covered in the documentation. Find out more.
In your case, SELECT 1 FROM DUAL; will simply returns 1. You need it because the INSERT ALL syntax demands a SELECT clause but you are not querying the input values from a table.
Brief re-introduction to one-row tables
Some SQL databases require all values to come FROM a table or table-like object, whereas others permit queries to construct values ex nihilo:
-- MySQL, sqlite, PostgreSQL, HSQLdb, and many others permit
-- a "naked" select:
SELECT 1;
-- Others *require* a FROM target, like Oracle.
SELECT 1 FROM DUAL;
-- ...and Firebird/Interbase:
SELECT 1 FROM RDB$DATABASE;
-- ...and DB2:
SELECT 1 FROM SYSIBM.SYSDUMMY1;
Here the cardinality of DUAL is important. If it had more than one row, your result set would have more than one row. What happens, for example, when you SELECT 1 FROM A_Table_With_Ten_Rows?
Why DUAL is used here
The SQL construct VALUES (<row-value-expression>) is a row value constructor. VALUES (1, 2, 3) "creates" a row of values just as SELECT 1, 2, 3 does.
Oracle, of course, requires that these values come FROM somewhere.
As a demonstration, instead of SELECTing from DUAL at the end of the INSERT ALL, try a table with N rows, and you'll see that each VALUES() row is inserted N times.
There are some samples about using dual in Queries:
select sysdate from dual /--it returns date of system
SELECT chr(223) FROM dual /--it returns character of AsciÙ‡i code
select my_sequence.nextval from dual; /-- It returns the next value of a sequence
select to_char(sysdate,'yyyy/mm/dd','nls_calendar=persian')from dual
/--returns persian date of system

Select distinct values from multiple columns in same table

I am trying to construct a single SQL statement that returns unique, non-null values from multiple columns all located in the same table.
SELECT distinct tbl_data.code_1 FROM tbl_data
WHERE tbl_data.code_1 is not null
UNION
SELECT tbl_data.code_2 FROM tbl_data
WHERE tbl_data.code_2 is not null;
For example, tbl_data is as follows:
id code_1 code_2
--- -------- ----------
1 AB BC
2 BC
3 DE EF
4 BC
For the above table, the SQL query should return all unique non-null values from the two columns, namely: AB, BC, DE, EF.
I'm fairly new to SQL. My statement above works, but is there a cleaner way to write this SQL statement, since the columns are from the same table?
It's better to include code in your question, rather than ambiguous text data, so that we are all working with the same data. Here is the sample schema and data I have assumed:
CREATE TABLE tbl_data (
id INT NOT NULL,
code_1 CHAR(2),
code_2 CHAR(2)
);
INSERT INTO tbl_data (
id,
code_1,
code_2
)
VALUES
(1, 'AB', 'BC'),
(2, 'BC', NULL),
(3, 'DE', 'EF'),
(4, NULL, 'BC');
As Blorgbeard commented, the DISTINCT clause in your solution is unnecessary because the UNION operator eliminates duplicate rows. There is a UNION ALL operator that does not elimiate duplicates, but it is not appropriate here.
Rewriting your query without the DISTINCT clause is a fine solution to this problem:
SELECT code_1
FROM tbl_data
WHERE code_1 IS NOT NULL
UNION
SELECT code_2
FROM tbl_data
WHERE code_2 IS NOT NULL;
It doesn't matter that the two columns are in the same table. The solution would be the same even if the columns were in different tables.
If you don't like the redundancy of specifying the same filter clause twice, you can encapsulate the union query in a virtual table before filtering that:
SELECT code
FROM (
SELECT code_1
FROM tbl_data
UNION
SELECT code_2
FROM tbl_data
) AS DistinctCodes (code)
WHERE code IS NOT NULL;
I find the syntax of the second more ugly, but it is logically neater. But which one performs better?
I created a sqlfiddle that demonstrates that the query optimizer of SQL Server 2005 produces the same execution plan for the two different queries:
If SQL Server generates the same execution plan for two queries, then they are practically as well as logically equivalent.
Compare the above to the execution plan for the query in your question:
The DISTINCT clause makes SQL Server 2005 perform a redundant sort operation, because the query optimizer does not know that any duplicates filtered out by the DISTINCT in the first query would be filtered out by the UNION later anyway.
This query is logically equivalent to the other two, but the redundant operation makes it less efficient. On a large data set, I would expect your query to take longer to return a result set than the two here. Don't take my word for it; experiment in your own environment to be sure!
try something like SubQuery:
SELECT derivedtable.NewColumn
FROM
(
SELECT code_1 as NewColumn FROM tbl_data
UNION
SELECT code_2 as NewColumn FROM tbl_data
) derivedtable
WHERE derivedtable.NewColumn IS NOT NULL
The UNION already returns DISTINCT values from the combined query.
Union is applied wherever the row data required is similar in terms of type, values etc. It doesnt matter you have column in the same table or the other to retrieve from as the results would remain the same ( in one of the above answers already mentioned though).
As you didn't wanted duplicates theres no point using UNION ALL and use of distinct is simply unnecessary as union gives distinct data
Can create a view would be best choice as view is a virtual representation of the table. Modifications could be then done neatly on that view created
Create VIEW getData AS
(
SELECT distinct tbl_data.code_1
FROM tbl_data
WHERE tbl_data.code_1 is not null
UNION
SELECT tbl_data.code_2
FROM tbl_data
WHERE tbl_data.code_2 is not null
);
Try this if you have more than two Columns:
CREATE TABLE #temptable (Name1 VARCHAR(25),Name2 VARCHAR(25))
INSERT INTO #temptable(Name1, Name2)
VALUES('JON', 'Harry'), ('JON', 'JON'), ('Sam','harry')
SELECT t.Name1+','+t.Name2 Names INTO #t FROM #temptable AS tSELECT DISTINCT ss.value FROM #t AS t
CROSS APPLY STRING_SPLIT(T.Names,',') AS ss

select a column where the column name is retrieved from a query

I'm looking for a elegant way to select a column from table A where as the column name is retrieved from a query on table B.
A query on table B results in 'col01'
The Table A has several columns named 'col01','col02','col03',...
Final query should be for result
result from B | effective SQL query
'col01' | SELECT col01 FROM A
'col02' | SELECT col02 FROM A
I'm looking for pure SQL solution with no scripting. It should run with Oracle and/or MySQL.
I'm looking for pure SQL solution with no scripting.
This is not possible. You have to create the statements dynamically.
In a very simple case you can just about do it with a CASE statement, but this is unlikely to be of much use in the real world:
with a as (
select 'col_01_val_01' as col_01, 'col_02_val_01' as col_02,
'col_03_val_01' as col_03 from dual
union select 'col_01_val_02' as col_01, 'col_02_val_02' as col_02,
'col_03_val_02' as col_03 from dual
union select 'col_01_val_03' as col_01, 'col_02_val_03' as col_02,
'col_03_val_03' as col_03 from dual),
b as (
select 1 parm, 'col_01' value from dual
union select 2 parm, 'col_02' value from dual
union select 3 parm, 'col_03' value from dual)
select b.value as result_from_b,
case b.value
when 'col_01' then col_01
when 'col_02' then col_02
when 'col_03' then col_03 end as result_from_a
from a, b
where b.parm = 1;
RESULT_FROM_B RESULT_FROM_A
------------- -------------
col_01 col_01_val_01
col_01 col_01_val_02
col_01 col_01_val_03
The columns have to be the same type (or at least expressible as such in the case), and b can only return one row... And it isn't very pretty of course. For anything more complicated you need dynamic SQL as #a_horse_with_no_name has already suggested.
This could be done within a stored routine in MySQL. I don't know about Oracle as I haven't used it. You can find out more about MySQL stored procedures here and here (the 2nd link is a pretty good PDF which walks you through some simple examples).