I need to join the results of two queries horizontally.
Consider a query below which will return two rows:
Select *
from Salary
where sal > 10000
The result of the query above should be joined side by side with the result of the query below which will again return two rows.Or I need to just concatenate the two result sets:
Select 'xyz' from dual
union
Select 'abc' from dual
Please suggest how this can be done as I tried to do this with the query below but it returns a cartesian product:
Select *
from (Select *
from salary
where sal > 10000) TEMP1,
(Select 'xyz' from dual
union
Select 'abc' from dual) TEMP2
You can do that by joining on rownum like this:
SELECT *
FROM
(SELECT view_name, rownum AS r FROM all_views WHERE rownum <=10)
FULL OUTER JOIN (SELECT table_name, rownum AS r FROM all_tables WHERE rownum <=10) USING (r)
In your case this would look like (untested):
Select * from
(Select salary.*, rownum AS r from salary where sal>10000) TEMP1
FULL OUTER JOIN
(SELECT temp2.*, rownum r FROM
(Select 'xyz' from dual
union
Select 'abc' from dual) TEMP2)
USING (r)
you can introduce an artificial join column:
SELECT *
FROM (SELECT s.*, ROWNUM ID FROM Salary s WHERE sal > 10000) q1
JOIN (SELECT 'xyz' col1, 1 ID
FROM dual
UNION
SELECT 'abc' col1, 2 ID FROM dual) q2 ON q1.id = q2.id
Thank you very much for your help.
But what I need is a bit complicated. I have updated the previous query to be somewhat like below instead of simple query that I posted before (SELECT * FROM Salary WHERE sal > 10000):
SELECT name, sal, address
FROM (SELECT e1.name, s1.sal, s1.grade, s2.address FROM Emp e1, salary s1,
(Select empcode, address FROM Address WHERE empcode LIKE 'NY%') s2
WHERE e1.hiredate =201001
AND s1.sal>10000)
I know the above query does not make much of a relevance. However, this is similar to what I need actually. I am not posting the original one as that is very complicated but if this can be done for this query, then I will be able to replicate the same on the original one as well.
Thank you,
Sharon
Related
I have a query with union all functionality each giving me count(*) return from respective queries and another count query like below. I want an outer query that gives the total.
1st query
select count(*) from a
union all
select count(*) from b;
Sample result for 1st query:
COUNT
10
40
2nd query
select count(*) from xy;
Sample result for 2nd query:
COUNT
20
I want output like this in 2 rows:
TABLES
COUNT
xy
20
ab
50
something like above. How can I achieve this in oracle? please suggest the best way to do this.
I wrote a select and union all but not sure how to proceed further.
One option is to sum counts returned by the 1st query and then union it with the 2nd; also, add constants which show the source:
select 'ab' what, (select count(*) from a) + (select count(*) from b) cnt from dual
union all
select 'xy', count(*) from xy;
You can use:
SELECT 'ab' AS type,
COUNT(*) AS total
FROM ( SELECT 1 FROM a UNION ALL
SELECT 1 from b );
UNION ALL
SELECT 'xy', COUNT(*)
FROM xy;
You can sum counts from your three unioned Select statements and group the result by combination of sources:
WITH
a AS
( Select LEVEL "A_ID", 'some column a' "COL_A" From Dual Connect By LEVEL <= 30 ),
b AS
( Select LEVEL "B_ID", 'some column b' "COL_B" From Dual Connect By LEVEL <= 20 ),
xy AS
( Select LEVEL "XY_ID", 'some column xy' "COL_XY" From Dual Connect By LEVEL <= 20 )
with above sample data it is like here:
SELECT
CASE WHEN SOURCE IN('a', 'b') THEN 'ab' ELSE SOURCE END "SOURCE",
Sum(CNT) "CNT"
FROM
( Select 'a' "SOURCE", Count(*) "CNT" From a Union All
Select 'b', Count(*) From b Union All
Select 'xy', Count(*) From xy
)
GROUP BY
CASE WHEN SOURCE IN('a', 'b') THEN 'ab' ELSE SOURCE END
--
-- R e s u l t :
-- SOURCE CNT
-- ------ ----------
-- ab 50
-- xy 20
Assuming that your real queries can be a lot more complex, I take it as a given that we shall not try to change them and somehow merge or split them.
Your first query returns two rows. You want to get their sum, so you must aggregate the result and use SUM.
Below query uses CTEs (subqueries in the WITH clause) for your two queries, and then a query that gets this sum. It then uses these CTEs for the final UNION ALL query.
with query1 (cnt) as (select count(*) from a union all select count(*) from b)
, query2 (cnt) as (select count(*) from xy)
, sumquery1 (total) as (select sum(cnt) from query1)
select 'ab' as tables, total from sumquery1
union all
select 'xy' as tables, cnt from query2
order by tables desc;
Is there a way to order the union of two select all statements based on table column values.
My sample code is:
SELECT * FROM emp WHERE mgr='7839'
UNION
SELECT * FROM emp WHERE NOT EXISTS (SELECT * FROM emp WHERE mgr='7839')
AND empno='7839'
order by ename;
This code is showing error as:invalid identifier 'ENAME'.
I am not using specific columns in select statement instead of * since there are more than 10 columns in the table and the code looks so big.
But ename is a column in emp.
will you consider small change in your query.
SELECT * FROM
(SELECT * FROM emp WHERE mgr='7839'
UNION
SELECT * FROM emp WHERE NOT EXISTS (SELECT * FROM emp WHERE mgr='7839')
AND empno='7839') AA
order by AA.ename;
Why would use use union for this? Just do:
SELECT e.*
FROM emp e
WHERE e.mgr = '7839' OR
(NOT EXISTS (SELECT 1 FROM emp e2 WHERE e2.mgr = '7839') AND
empno = '7839'
)
ORDER BY ename;
In Oracle below query is working fine with single column but when I tried to put multiple columns it fails, Actually my requirement is to Exit SQL query if there is no records in particular table and its complex inner query (below is simplified problem description) and I cannot use PL/SQL block, please suggest.
SQL> select
case when (select count(*) from bl1_charge_adj where rownum=1) = '1' then ( select customer_id from customer)
else 44 END as ee
from dual;
EE
----------
44
SQL> select
case when (select count(*) from bl1_charge_adj where rownum=1) = '1' then ( select customer_id,DL_UPDATE_STAMP from customer)
else (1,2) END
from dual
ERROR at line 1:
ORA-00907: missing right parenthesis
I think you want something like this:
select customer_id, DL_UPDATE_STAMP
from customer
where exists (select 1 from bl1_charge_adj)
union all
select 1, 2
from dual
where not exists (select 1 from bl1_charge_adj);
This should work:
select nvl(c.customer_id, 1), nvl(c.DL_UPDATE_STAMP, 2)
from ( select count(*) as c from bl1_charge_adj where rownum=1) d
left outer join customer c on d.c = 1;
I suspect it would be better done by changing the count(*) to something else if the bl1_charge_adj table is big.
I'm trying to do multiple select from diff tables and just have a result in one column.
SELECT COUNT(*) FROM tb1 union
SELECT COUNT(*) FROM tb2 union
SELECT COUNT(*) FROM tb3;
output should be like:
593643
18103600
0
Problem with this is that the result is being arranged on desc order.
Like below:
0
593643
18103600
I would want the result to be as I put the select statement.
Please advise. Btw, I'm using teradata.
Thank you.
SQL result sets are inherently unordered, unless you explicitly specify an order by clause. You can do this with a subquery:
select cnt
from ((SELECT COUNT(*) as cnt, 1 as ord FROM tb1)
union all
(SELECT COUNT(*), 2 FROM tb2)
union all
(SELECT COUNT(*), 3 FROM tb3)
) t
order by ord
If you want specific order, add ORDER BY clause. It would also be good to use UNION ALL so you always get 3 rows, even with duplicate results (two tables having the same number of rows):
SELECT 'tbl1' AS tablename, COUNT(*) AS cnt, 1 AS ord FROM tb1 UNION ALL
SELECT 'tbl2', COUNT(*), 2 FROM tb2 UNION ALL
SELECT 'tbl3', COUNT(*), 3 FROM tb3
ORDER BY ord ;
I tried the sql query given below:
SELECT * FROM (SELECT *
FROM TABLE_A ORDER BY COLUMN_1)DUMMY_TABLE
UNION ALL
SELECT * FROM TABLE_B
It results in the following error:
The ORDER BY clause is invalid in views, inline functions, derived
tables, subqueries, and common table expressions, unless TOP or FOR
XML is also specified.
I need to use order by in union all. How do I accomplish this?
SELECT *
FROM
(
SELECT * FROM TABLE_A
UNION ALL
SELECT * FROM TABLE_B
) dum
-- ORDER BY .....
but if you want to have all records from Table_A on the top of the result list, the you can add user define value which you can use for ordering,
SELECT *
FROM
(
SELECT *, 1 sortby FROM TABLE_A
UNION ALL
SELECT *, 2 sortby FROM TABLE_B
) dum
ORDER BY sortby
You don't really need to have parenthesis. You can sort directly:
SELECT *, 1 AS RN FROM TABLE_A
UNION ALL
SELECT *, 2 AS RN FROM TABLE_B
ORDER BY RN, COLUMN_1
Not an OP direct response, but I thought I would jimmy in here responding to the the OP's ERROR messsage, which may point you in another direction entirely!
All these answers are referring to an overall ORDER BY once the record set has been retrieved and you sort the lot.
What if you want to ORDER BY each portion of the UNION independantly, and still have them "joined" in the same SELECT?
SELECT pass1.* FROM
(SELECT TOP 1000 tblA.ID, tblA.CustomerName
FROM TABLE_A AS tblA ORDER BY 2) AS pass1
UNION ALL
SELECT pass2.* FROM
(SELECT TOP 1000 tblB.ID, tblB.CustomerName
FROM TABLE_B AS tblB ORDER BY 2) AS pass2
Note the TOP 1000 is an arbitary number. Use a big enough number to capture all of the data you require.
There will be times when you need to do something like this :
Pull top 5 from table 1 based on a sort
and bottom 5 from table 2 based on another sort
and union these together.
solution
select * from (
-- top 5 records
select top 5 col1, col2, col3
from table1
group by col1, col2
order by col3 desc ) z
union all
select * from (
-- bottom 5 records
select top 5 col1, col2, col3
from table2
group by col1, col2
order by col3 ) z
this was the only way i was able to get around the error and worked fine for me.
SELECT * FROM (SELECT *
FROM TABLE_A ORDER BY COLUMN_1)DUMMY_TABLE
UNION ALL
SELECT * FROM TABLE_B
ORDER BY 2;
2 is column number here .. In Oracle SQL you can use the column number by which you want to sort the data
This solved my SELECT statement:
SELECT * FROM
(SELECT id,name FROM TABLE_A
UNION ALL
SELECT id,name FROM TABLE_B ) dum
order by dum.id , dum.name
where id and name columns available in tables and you can use your columns .
Simply use that , no need parenthesis or anything else
SELECT *, id as TABLE_A_ID FROM TABLE_A
UNION ALL
SELECT *, id as TABLE_B_ID FROM TABLE_B
ORDER BY TABLE_A_ID, TABLE_B_ID
ORDER BY after the last UNION should apply to both datasets joined by union.
The solution shown below:
SELECT *,id AS sameColumn1 FROM Locations
UNION ALL
SELECT *,id AS sameColumn2 FROM Cities
ORDER BY sameColumn1,sameColumn2
select CONCAT(Name, '(',substr(occupation, 1, 1), ')') AS f1
from OCCUPATIONS
union
select temp.str AS f1 from
(select count(occupation) AS counts, occupation, concat('There are a total of ' ,count(occupation) ,' ', lower(occupation),'s.') As str from OCCUPATIONS group by occupation order by counts ASC, occupation ASC
) As temp
order by f1