Column names for a table formed by a UNION - sql

Given a couple of simple tables like so:
create table R(foo text);
create table S(bar text);
If I were to union them together in a query, what do I call the column?
select T.????
from (
select foo
from R
union
select bar
from S) as T;
Now, in mysql, I can apparently refer to the column of T as 'foo' -- the name of the matching column for the first relation in the union. In sqlite3, however, that doesn't seem to work. Is there a way to do it that's standard across all SQL implementations?
If not, how about just for sqlite3?
Correction: sqlite3 does allow you to refer to T's column as 'foo' after all! Oops!

Try to give an alias to columns;
select T.Col1
from (
select foo as Col1
from R
union
select bar as Col1
from S) as T;
or If the name of column is not necessary then T.* will be enough.

Although there is no spelled rule, we can use the column names from the first subquery in the union query to fetch the union results.

you only need column aliases only in first select (tested in SQl Server 2008 R2)
select T.Col1
from (
select 'val1' as Col1
union
select 'val2'
union
select 'val3'
) as T;

Related

The purpose of 'value' keyword in Oracle Select Statement

Whats is the difference between:
select 'mari makan' value from dual ;
and
select 'mari makan' from dual ;
when querying from oracle table.
Precisely, what is the purpose of value keyword in above statement?
The first names the column value. It is more typically written using as:
select 'mari makan' as value
from dual ;
The second does not give a user-defined name to the column.
The difference between them is that the first query aliasing this column, and giving it a unique name, while the other one doesn't.
What does that mean?
SELECT * FROM (
SELECT 'asda' FROM dual
UNION
SELECT 'asdasda' FROM dual
)
WHERE ??? = ??
This query is not aliasing the column, if you would want to use this column in the other query, you will have a problem. I think the default is to name the column after what you selected, which means it will be named 'asda' .
As opposed to:
SELECT * FROM (
SELECT 'asda' Col1 FROM dual
UNION
SELECT 'asdasda' as Col1 FROM dual
) WHERE Col1 <> 'asda'
Which will let you call this column from an outer query.
The standard is to write it as SELECT <Col> AS <New_Name> but it can be written with out the AS as well.

Oracle query expression too long to execute [duplicate]

It is possible to put more than 1000 items in the SQL IN clause? We have been getting issues with our Oracle database not being able to handle it.
IF yes, how do we put more than 1000 items in the SQL IN clause?
IF not, what else can I do?
There's another workaround for this that isn't mentioned in any of the other answers (or other answered questions):
Any in statement like x in (1,2,3) can be rewritten as (1,x) in ((1,1), (1,2), (1,3)) and the 1000 element limit will no longer apply. I've tested with an index on x and explain plan still reports that Oracle is using an access predicate and range scan.
You should transform the IN clauses to INNER JOIN clauses.
You can transform a query like this one
SELECT foo
FROM bar
WHERE bar.stuff IN
(SELECT stuff FROM asdf)
in a query like this other one.
SELECT b.foo
FROM (
SELECT DISTINCT stuff
FROM asdf ) a
JOIN bar b
ON b.stuff = a.stuff
You will also gain a lot of performance
We can have more than one "IN" statement for the same variable.
For ex:
select val
from table
where val in (1,2,3,...)
or
val in (7,8,9,....)
If you don't have the luxury of creating a temp table, you can simulate it using the WITH clause
with t as (
select 1 val from dual
union all select 2 from dual
union all select 3 from dual
...
union all select 5001 from dual
union all select 5002 from dual
)
select *
from mytable
where col1 in (select val from t)
Obviously, you could also join mytable to t
I like Gordy's answer best, just showing another way.
Another way:
SELECT COL1, COL2, COL3 FROM YOUR_TABLE
WHERE 1=1
AND COL2 IN (
SELECT VAL1 as FAKE FROM DUAL
UNION
SELECT VAL2 as FAKE FROM DUAL
UNION
SELECT VAL3 as FAKE FROM DUAL
--...
)

Returning not found values in query

I'm working on a project, and I have a list of several thousand records that I need check. I need to provide the list of the ones NOT found, and provide the query I use to locate them so my superiors can check their work.
I'll admit I'm relatively new to SQL. I don't have access to create temporary tables, which is one way I had thought of to do this.
A basic idea of what I'm doing:
select t.column1, t.column2
from table1 t
where t.column1 in ('value1','value2','value3')
If value1 and value3 are in the database, but value2 is not, I need to display value2 and not the others.
I have tried ISNULL, embedding the query, and trying to select NOT values from the query.
I have searched for returning records not found in a query on Google and on this site, and still found nothing.
I have tried something similar:
First create a table which will contain all such values that you need.
lets say
create table table_values(values varchar2(30));
then try the in clause as below:
select * from table_values tv where tv.value not in (select t.column1
from table1 t);
this will return the values needed.
In SQL Server 2008, you can make derived tables using the syntax VALUES(...)(...)(...), e.g.
select v.value
from (
values ('value1'),('value2'),('value3')
) v(value)
left join table1 t on t.column1 = v.value
where t1.column1 is null
Notes:
Each (...) after VALUES is a single row, and you can have multiple columns.
The v(value) after the derived table is the alias given to the table, and column name(s).
LEFT JOIN keeps the values from the derived table v even when the record doesn't exist in table1
Then, we keep only the records that cannot be matched, i.e. t1.column1 is null
I've switched the first column in your select to the column from v. column2 is removed because it is always null
solution might work in Oracle where dual is single row single column table. You need
one table where you can make virtual select of desired values!
WARNING as I don't have access to db I never tested query below.
SELECT tab_all.col_search, t.column1, t.column2
FROM
(
Select value1 AS col_search from dual
union all
Select value2 from dual
union all
Select value3 from dual
) tab_all left join table1 t
on col_search = t.column1
WHERE t.column1 is null;
I belive sqlserver equivalent of Oracle's
SELECT value1 FROM dual is
SELECT value1 OR SELECT 'value1'.
So try
SELECT tab_all.col_search, t.column1, t.column2
FROM
(
Select value1 AS col_search
union all
Select value2 AS col_search
union all
Select value3 AS col_search
) tab_all left join table1 t
on col_search = t.column1
WHERE t.column1 is null;
As I am not sqlserver person might be that
RichardTheKiwi version of Oracle's select from dual is better.

input string to table

I am doing some debugging in SQL for oracle 10g. I have a big input string which is used in "IN Clause" i.e.
select * from table where col in ('str2','str3','str4','str5',...)
i want to convert the in clause to rows or table?
Is there a way to do this i.e.
select 'str2','str3','str4','str5', .. from dual
but this outputs multiple columns and i want multiple rows?
Edit:
Here is what i am trying to do. suppose i have an excel data in tmp_table1 (cant create in reality) and tmp_table1 is same as the IN clause, then the below statement will give the missing keys.
SELECT *
FROM tmp_table1
WHERE unique_id NOT IN (
SELECT unique_id
FROM table1
WHERE unique_id IN
('str1', 'str2', 'str3', 'str4'))
now #andriy-m solution works if the in string is less than 4000. but what if its greater?
You are probably looking for this solution.
You can UNION the values into multiple rows:
SELECT 'str2' AS col FROM dual
UNION
SELECT 'str3' FROM dual
UNION
SELECT 'str4' FROM dual
UNION
SELECT 'str5' FROM dual

Single SQL SELECT Returning multiple rows from one table row

We have a table which is of the form:
ID,Value1,Value2,Value3
1,2,3,4
We need to transform this into.
ID,Name,Value
1,'Value1',2
1,'Value2',3
1,'Value3',4
Is there a clever way of doing this in one SELECT statement (i.e without UNIONs)? The column names Value1,Value2 and Value3 are fixed and constant.
The database is oracle 9i.
Give a union a shot.
select ID, 'Value1' as Name, Value1 as Value from table_name union all
select ID, 'Value2', Value2 as Value from table_name union all
select ID, 'Value3', Value3 as Value from table_name
order by ID, Name
using union all means that the server won't perform a distinct (which is implicit in union operations). It shouldn't make any difference with the data (since your ID's should HOPEFULLY be different), but it might speed it up a bit.
This works on Oracle 10g:
select id, 'Value' || n as name,
case n when 1 then value1 when 2 then value2 when 3 then value3 end as value
from (select rownum n
from (select 1 from dual connect by level <= 3)) ofs, t
I think Oracle 9i had recursive queries? Anyway, I'm pretty sure it has CASE support, so even if it doesn't have recursive queries, you can just do "(select 1 from dual union all select 2 from dual union all select 3 from dual) ofs" instead. Abusing recursive queries is a bit more general- for Oracle. (Using unions to generate rows is portable to other DBs, though)
You can do it like this, but it's not pretty:
SELECT id,'Value 1' AS name,value1 AS value FROM mytable
UNION
SELECT id,'Value 2' AS name,value2 AS value FROM mytable
UNION
SELECT id,'Value 3' AS name,value3 AS value FROM mytable
Unioning three select statements should do the trick:
SELECT ID, 'Value1', Value1 AS Value
FROM TABLE
UNION
SELECT ID, 'Value2', Value2 AS Value
FROM TABLE
UNION
SELECT ID, 'Value3', Value3 AS Value
FROM TABLE
If you're using SQL Server 2005+ then you can use UNPIVOT
CREATE TABLE #tmp ( ID int, Value1 int, Value2 int, Value3 int)
INSERT INTO #tmp (ID, Value1, Value2, Value3) VALUES (1, 2, 3, 4)
SELECT
*
FROM
#tmp
SELECT
*
FROM
#tmp
UNPIVOT
(
[Value] FOR [Name] IN (Value1, Value2, Value3)
) uPIVOT
DROP TABLE #tmp
A UNION ALL, as others have suggested, is probably your best bet in SQL. You might also want to consider handling this in the front end depending on what your specific requirements are.
CTE syntax may be different for Oracle (I ran it in Teradata), but I only used CTE to provide test data, those 1 2 3 and 4. You can use temp table instead. The actual select statement is plain vanilla SQL and it will on any relational database.
For Sql Server, consider UNPIVOT as an alternative to UNION:
SELECT id, value, colname
FROM #temp t
UNPIVOT (Value FOR ColName IN (value1,value2,value3)) as X
This will return the column name as well. I'm unsure what the X is used for, but you can't leave it out.
Try this:
CTE creates a temp table with 4 values. You can run this as is in any database.
with TEST_CTE (ID) as
(select * from (select '1' as a) as aa union all
select * from (select '2' as b) as bb union all
select * from (select '3' as c) as cc union all
select * from (select '4' as d) as dd )
select a.ID, 'Value'|| a.ID, b.ID
from TEST_CTE a, TEST_CTE b
where b.ID = (select min(c.ID) from TEST_CTE c where c.ID > a.ID)
Here is the result set:
1 Value1 2
2 Value2 3
3 Value3 4
Enjoy!
Some afterthoughts.
^^^ CTE syntax may be different in Oracle. I could only run it in Teradata. You can substitute it with temp table or fix the syntax to make it Oracle compatible. The select statement is plain vanilla SQL that will work on any database.
^^^ Another thing to note. If ID field is numeric, you might need to cast it into CHAR in order to concatenate it with "Value".