Oracle create table using with clause - sql

Can I create a table from a query formed using with clause?

Sure:
CREATE TABLE t
AS
WITH some_data AS (
SELECT 1 as some_value
FROM dual
UNION ALL
SELECT 2
FROM dual
)
SELECT *
FROM some_data

The CREATE TABLE table_name AS statement creates a table based on a select statement. The solution for a with clause will be :
CREATE TABLE t
AS
SELECT * FROM (
WITH some_data AS (
SELECT 1 as some_value
FROM dual
UNION ALL
SELECT 2
FROM dual
)
);

For multiple CTE (common table expressions; i.e. multiple WITH clause), I found the same syntax worked. i.e.
CREATE TABLE schema.table_name as
WITH table1 as (SELECT 1),
table2 as (SELECT 2)
select * from table2
will create the table_name in the schema from the select statement

Related

Perform a function after union of two tables

I have two tables that I want to union together then perform some math functions on the combined table.
I know how to do the math for each separate table, but throwing in a union table to go off of is out of my league.
Here's the math for one table using column header "UnitsReceived" and "AsnPsUnits"
The other table would have headers: "cUnitsReceived" and "cAsnPsUnits"
select VendName,
1-abs(((cast(sum(UnitsReceived) as decimal(5,0))) - (cast(sum(AsnPsUnits) as decimal(5,0)))) /(cast(sum(AsnPsUnits) as decimal(5,0)))) as ASNpsAcc
from VenTest2
where ID<20
group by VendName
How would I perform this function after the union of two tables?
You'll need to get the unioned tables into some table object before performing your function. This could be done using:
A Common Table Expression
with cte as (
select ID, VALUE from A
union all
select ID, VALUE from B
)
select
*
,myfunction(VALUE) as MyFunctionResult
from
cte
A temp table
select ID, VALUE into #myTempTable from A
insert into #myTempTable select ID, VALUE from B
select
*
,myfunction(VALUE) as MyFunctionResult
from
#myTempTable
A table variable
declare #myTableVariable table (ID int, VALUE decimal)
insert into #myTableVariable
select ID, VALUE from A
union all
select ID, VALUE from B
select
*
,myfunction(VALUE) as MyFunctionResult
from
#myTableVariable
A sub query
select
*
,myfunction(VALUE) as MyFunctionResult
from
(
select ID, VALUE from A
union all
select ID, VALUE from B
) mySubQuery
This will help with the subq being the union
select VendName,
1-abs(((cast(sum(UnitsReceived) as decimal(5,0))) - (cast(sum(AsnPsUnits) as decimal(5,0)))) /(cast(sum(AsnPsUnits) as decimal(5,0)))) as ASNpsAcc
from
(
select ID, UnitsReceived, AsnPsUnits from VenTest2 where ID<20
union
select ID1, UnitsReceived1, AsnPsUnits1 from VenTest1
)a
group by VendName
This is not the way, brothers:
select VendName,
1-abs(((cast(sum(UnitsReceived) as decimal(10,2))) - (cast(sum(AsnPsUnits) as decimal(10,2)))) /(cast(sum(AsnPsUnits) as decimal(10,2)))) as ASNpsAcc
from VenTest2
where ID<10
group by VendName
union
select cVendName,
1-abs(((cast(sum(cUnitsReceived) as decimal(10,2))) - (cast(sum(casnpsunits) as decimal(10,2)))) /(cast(sum(cAsnPsUnits) as decimal(10,2)))) as ASNpsAcc
from CTest
where id <10
group by cvendname

How to join multiple CTE's into a temp table

I have been given a script to clean up which uses approx 85 temp tables, I have been advised to use Common Table Expressions.
I have 3 CTE's, the first is the result of 7 tables pulled together using Union all. Followed by 2 more CTE's. The script runs up to:
select * from CTE_1
Union all
select * from CTE_2
Union all
select * from CTE_3
I then want to put all these results into a reusable table so I can then add some joins with various case statement logic. How can I put these into a temp table so that I can reference it later.
I'm looking to reduce the amount of temp tables so rather than put each CTE into a temp table I would ideally put multiple CTE's into one temp table. I currently have:
; with [CTE One] as (
select 1 as col
),
[CTE Two] as (
select 2 as col
),
[CTE Three] as (
select 3 as col
)
select * from CTE_1
Union all
select * from CTE_2
Union all
select * from CTE_3
Alternatively..
IF ( OBJECT_ID('tempdb..#temptable') IS NOT NULL )
BEGIN
DROP TABLE #temptable
END
CREATE TABLE #temptable
(
val int
)
;
WITH [CTE One]
AS ( SELECT 1 AS col
),
[CTE Two]
AS ( SELECT 2 AS col
),
[CTE Three]
AS ( SELECT 3 AS col
)
INSERT INTO #temptable (val)
SELECT *
FROM ( SELECT *
FROM CTE_1
UNION ALL
SELECT *
FROM CTE_2
UNION ALL
SELECT *
FROM CTE_3
) T
Can't you just use into?
select *
into #temptable
from CTE_1
Union all
select * from CTE_2
Union all
select * from CTE_3;
I might also be inclined to use a table variable, if the code is structured appropriately.

How to create table with multiple rows and columns using only SELECT clause (i.e. using SELECT without FROM clause)

I know that in SQL Server, one can use SELECT clause without FROM clause, and create a table with one row and one column
SELECT 1 AS n;
But I was just wondering, is it possible to use SELECT clause without FROM clause, to create
a table with one column and multiple rows
a table with multiple columns and one row
a table with multiple columns and multiple rows
I have tried many combinations such as
SELECT VALUES(1, 2) AS tableName(n, m);
to no success.
You can do it with CTE and using union(Use union all if you want to display duplicates)
Rextester Sample for all 3 scenarios
One Column and multiple rows
with tbl1(id) as
(select 1 union all
select 2)
select * from tbl1;
One row and multiple columns
with tbl2(id,name) as
(select 1,'A')
select * from tbl2;
Multiple columns and multiple rows
with tbl3(id,name) as
(select 1,'A' union all
select 2,'B')
select * from tbl3;
-- One column, multiple rows.
select 1 as ColumnName union all select 2; -- Without FROM;
select * from ( values ( 1 ), ( 2 ) ) as Placeholder( ColumnName ); -- With FROM.
-- Multiple columns, one row.
select 1 as TheQuestion, 42 as TheAnswer; -- Without FROM.
select * from ( values ( 1, 42 ) ) as Placeholder( TheQuestion, TheAnswer ); -- With FROM.
-- Multiple columns and multiple rows.
select 1 as TheQuestion, 42 as TheAnswer union all select 1492, 12; -- Without FROM.
select * from ( values ( 1, 2 ), ( 2, 4 ) ) as Placeholder( Column1, Column2 ); -- With FROM.
You can do all that by using UNION keyword
create table tablename as select 1 as n,3 as m union select 2 as n,3 as m
In Oracle it will be dual:
create table tablename as select 1 as n,3 as m from dual union select 2 as n,3 as m from dual
You can use UNION operator:
CREATE TABLE AS SELECT column_name(s) FROM table1
UNION
SELECT column_name(s) FROM table2;
The UNION operator selects only distinct values by default. To allow duplicate values you can use UNION ALL.
The column names in the result-set are usually equal to the column names in the first SELECT statement in the UNION.
try this:
--1) a table with one column and multiple rows
select * into tmptable0 from(
select 'row1col1' as v1
union all
select 'row2col1' as v1
) tmp
--2) a table with multiple columns and one row
select 'row1col1' as v1, 'row1col2' as v2 into tmptable1
--3) a table with multiple columns and multiple rows
select * into tmptable2 from(
select 'row1col1' as v1, 'row1col2' as v2
union all
select 'row2col1' as v2, 'row2col2' as v2
) tmp
One can create a view and later can query it whenever required
-- table with one column and multiple rows
create view vw1 as
(
select 'anyvalue' as col1
union all
select 'anyvalue' as col1
)
select * from vw1
-- table with multiple columns and multiple rows
create view vw2 as
(
select 'anyvalue1' as col1, 'anyvalue1' as col2
union all
select 'anyvalue2' as col1, 'anyvalue2' as col2
)
select * from vw2

Can I nest "WITH" clause in Oracle SQL?

Following query gives me an error:
"ORA-32034: Unsupported use of WITH clause"
WITH table_B as
(
SELECT * FROM (
WITH table_A AS
(SELECT 'Akshay' as NAME FROM DUAL)
SELECT NAME FROM table_A
) WHERE NAME LIKE '%Aks%' ---<<< Note a filter here
)
SELECT * from table_B;
Is there a way out? Thanks
You should change your query to:
WITH table_a AS
(
SELECT 'Akshay' as name
FROM dual
)
,table_b AS
(
SELECT name
FROM table_a
WHERE name LIKE '%Aks%'
)
SELECT *
FROM table_b;
We can use like following:-
WITH
table_A AS
(SELECT 'Akshay' as NAME FROM DUAL),
table_B AS
(SELECT * FROM table_A where NAME like 'Aks%') --<< Adding filter here now
SELECT * FROM table_B;
Cheers!

Oracle SQL Query IN

I have following query, that's not working.
select * from table where id in (
1,2, (select id from another_table)
)
How i can rewrite it?
How about
select * from table
where id in (1,2)
or id in (select id from another_table)
Take care and use parentheses when adding additional WHERE-conditions using and!!!
select *
from table
where id in (1,2) OR id in(
select id from another_table
)
select * from table where id in (
select 1 as id from dual
union all
select 2 as id from dual
union all
select id from another_table
)
select * from table where id in (
select 1 from dual
union all
select 2 from dual
union all
select id from another_table);
I'm using union because this is faster than using an OR clause which also can be used.