oracle sql - define date as variable in a with statement - sql

in oracle - i am trying to figure out how to define variables in a with statement.
when i define a variable as a number it works fine:
with a as(
select 100 as query_rows
from dual
)
,b as (
select * from table1 where rownum=query_rows
)
select * from b --working great
however,if i want to define a date as a variable,i keep getting an error:
with a as(
select DATE '2020-10-01' as query_date
from dual
)
,b as (
select * from table1 where table1.date=query_date
)
select * from b -- ORA-00904 : "query_date" is not a valid identifier
from oracle :ORA-00904
You tried to execute a SQL statement that included an invalid column name or the column name is missing. This commonly occurs when you reference an invalid alias in a SELECT statement.
so,why does the first query work and the second one doesn't?

You need to use the CTE table in query as follows:
with a as(
select DATE '2020-10-01' as query_date
from dual
)
,b as (
select * from table1 cross join a where table1.date=a.query_date
)
Select * from b;

It is possible, but you need to refer to cte you are using(here using subquery):
with a as(
select DATE '2020-10-01' as query_date
from dual
) ,b as (
select *
from table1
where table1.date = (SELECT query_date FROM a) -- IN if more than one row is allowed
)
select * from b

Adding to #Tejash, you don't need to use b:
with a as(
select DATE '2020-10-01' as query_date
from dual
)
select * from table1 cross join a where table1.date=a.query_date

Related

StartDate invalid identifier

I have two SELECT statment which I connect using UNION and I get error
ORA-00904: "PUSD2"."STARTDATE": invalid identifier
Since I create first one SELECT statment and run and I get result, and second also, so I run separatly and it works perfect. But when I use UNION I get error pusd2.StartDate invalid identifier.
SELECT * FROM project_users_schedule_dates pusd1
WHERE pusd1.UserID = 196 AND
pusd1.StartDate >= '2020-04-27' AND pusd1.EndDate <= '2020-06-06'
UNION
SELECT * FROM project_users_schedule_dates pusd2
WHERE pusd2.UserID = 196 AND
pusd2.StartDate <= '2020-04-27' AND pusd2. EndDate >= '2020-06-06'
ORDER BY pusd2.StartDate
What is wrong here ? What I made wrong ?
Table structure project_users_schedule_dates
The error likely stems from using an alias in the second union in your ORDER BY clause. However, I might suggest writing your query this way instead:
SELECT DISTINCT *
FROM project_users_schedule_dates
WHERE
UserID = 196 AND
(StartDate >= '2020-04-27' AND EndDate <= '2020-06-06' OR
StartDate <= '2020-04-27' AND EndDate >= '2020-06-06');
This approach brings together the critera from both sides of the union in a single WHERE clause. It then filters duplicates using DISTINCT, instead of the union. Note that in general doing SELECT * in a union query is not desirable, because it makes it impossible to see which columns are being included.
The problem is the ORDER BY clause. If you use UNION, you have to put the order by in an outline query
SQL> create table t ( c1 date ) ;
Table created.
SQL> insert into t values ( sysdate ) ;
1 row created.
SQL> select t.c1 from t union all select x.c1 from t x order by x.c1 ;
select t.c1 from t union all select x.c1 from t x order by x.c1
*
ERROR at line 1:
ORA-00904: "X"."C1": invalid identifier
You have to use an outline query with order by out of the union ( see below ) or use another approximation like the one provided in the other answer.
SQL> select * from ( select t.c1 from t union all select x.c1 from t x ) order by c1 ;
C1
---------
27-AUG-20
27-AUG-20
The way I see it, the last line of your query should be just
ORDER BY StartDate
(of course, if there's such a column in that query).

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

SQL statement to return non-intersection records

I was recently asked this question and was a little stumped so I want to ask the experts...
Given two tables A & B, I want to return all the values from A and B that do not overlap. Think of two overlapping circles; how do we return all the data that is NOT in the overlapping center section? And, I had to use ANSI Standard SQL rather than Oracle syntax.
Assuming we want everything exclusive to both A & B, my answer was
select *
from A
cross join B
minus
(select a.common_column from a
intersect
select b.common_column)
Does this look correct, or even close? If it is correct, is there a more efficient way to do this?
BTW - my solution was soundly rejected....
Thank you!
Given the tables A and B, you are looking for (A U B) - (A & B). In other words, you need A union B minus their intersection. Remember A and B must be union-compatible for this query to work. I would do:
(select * from A
union
select * from B
)
minus
(select * from A
intersect
select * from B
)
May be full outer join?
select coalesce(A.col, B.col)
from A full outer join B on A.col = B.col
where A.col is null or B.col is null;
For computing a set symmetric difference, you can use a combination of MINUS and UNION ALL:
select * from (
(select * from A
minus
select * from B)
union all
(select * from B
minus
select * from A)
)
Your query was rejected because it is syntactically incorrect: the number of columns differ and it confuses cross join and union all. However, I think you have the right idea for solving this.
You can easily fix this:
(select *
from A
union all
select *
from B
) minus
(select *
from A
intersect
select *
from B
);
That is, combine everything using union all and then subtract the rows that occur in both tables.
Of course, if there is a single id, then you can use the id with join and other operations.
Just like Frank Schmitt answered in the meantime:
Here it is including a data example:
WITH
table_a(name) AS (
SELECT 'From_A_1'
UNION ALL SELECT 'From_A_2'
UNION ALL SELECT 'From_A_3'
UNION ALL SELECT 'From_A_4'
UNION ALL SELECT 'From_A_5'
UNION ALL SELECT 'From_BOTH_6'
UNION ALL SELECT 'From_BOTH_7'
UNION ALL SELECT 'From_BOTH_8'
)
,
table_b(name) AS (
SELECT 'From_B_1'
UNION ALL SELECT 'From_B_2'
UNION ALL SELECT 'From_B_3'
UNION ALL SELECT 'From_B_4'
UNION ALL SELECT 'From_B_5'
UNION ALL SELECT 'From_BOTH_6'
UNION ALL SELECT 'From_BOTH_7'
UNION ALL SELECT 'From_BOTH_8'
)
(SELECT * FROM table_a EXCEPT SELECT * FROM table_b)
UNION ALL
(SELECT * FROM table_b EXCEPT SELECT * FROM table_a)
ORDER BY name
;
name
From_A_1
From_A_2
From_A_3
From_A_4
From_A_5
From_B_1
From_B_2
From_B_3
From_B_4
From_B_5
You will need to select all the data from both tables, except where they overlap, and then combine the data with a union. The code provided should work for your example.
SELECT *
FROM
(
SELECT * FROM Table1
EXCEPT SELECT * FROM Table2
)
UNION
SELECT *
FROM
(
SELECT * FROM Table2
EXCEPT SELECT * FROM Table1
)
Hope this helps.

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.