Reputation: 6252
I Have the following query which unions two smaller queries:
SELECT 'Static 1' type, somefield, some_id
FROM (SELECT some_id, somefield
FROM sometable
WHERE someothercolumn = 'Static 1'
and someid = :id)
UNION ALL
SELECT 'Static 1' type, somefield, some_id
FROM (SELECT some_id, somefield
FROM sometable
WHERE someothercolumn = 'Static 2'
and someid = :id)
If the query returns a row and query 2 returns a row then I will have two rows like this:
type | somefield | some_id
---------------------------------------------
Static 1 | somevalue | 1
Static 2 | somevalue | 1
Which is the output I want. If one of those two queries doesn't return a row (or even if both don't return a row) then I will have zero rows returned. This is not what I want. I always want the 'type' and the 'some_id' to return even if there is no data. So if both of those queries didn't have any data my expected result would be:
type | somefield | some_id
---------------------------------------------
Static 1 | | 1
Static 2 | | 1
I have tried to UNION ALL each query with a NOT EXISTS but that way the 'some_id
' would need to be some arbitrary hardcoded value. What I want is for it to always show the bind variable passed, :id
.
Upvotes: 1
Views: 1855
Reputation: 246918
Perhaps something like:
WITH a AS (/* subquery 1 */),
b AS (/* subquery 2 */)
SELECT (SELECT a.col1 FROM a),
(SELECT a.col2 FROM a),
...
FROM dual
UNION ALL
SELECT (SELECT b.col1 FROM b),
(SELECT b.col2 FROM b),
...
FROM dual
Upvotes: 1
Reputation: 164099
Make a CTE for your query and another CTE for the 2 extra rows and use UNION ALL and NOT EXISTS it like this:
WITH
cte1 AS (
<your query here>
),
cte2 AS (
SELECT 'Static 1' type, null somefield, :id FROM dual
UNION ALL
SELECT 'Static 2' type, null somefield, :id FROM dual
)
SELECT * FROM cte1
UNION ALL
SELECT * FROM cte2
WHERE NOT EXISTS (SELECT 1 FROM cte1)
Upvotes: 1
Reputation: 142798
One option is to select the header dummy row with the NOT EXISTS
to decide whether to return it (yes, if actual row in the table doesn't exist; no, if row exists).
Have a look at the example: see line #4 which is commented at the moment which means that your table doesn't contain row that satisfies that condition, so a dummy header row will be displayed:
SQL> with test (type, some_id) as
2 (select 'Static 99', 44 from dual union all
3 select 'Static 2' , 57 from dual
4 --union all select 'Static 1', 66 from dual -- toggle to see the difference
5 )
6 -- This is a header which won't be displayed if table contains
7 -- type = 'Static 1' and some_id = 66
8 select 'Static 1' type, 1 some_id
9 from dual
10 where not exists (select null
11 from test
12 where type = 'Static 1'
13 and some_id = 66
14 )
15 union all
16 -- This returns actual rows (if they exist)
17 select 'Static 1' type, some_id
18 from (select some_id
19 from test
20 where type = 'Static 1'
21 and some_id = 66
22 );
TYPE SOME_ID
-------- ----------
Static 1 1
SQL>
However, if it exists (line #4 uncommented), then actual data is displayed, without that dummy header row:
SQL> with test (type, some_id) as
2 (select 'Static 99', 44 from dual union all
3 select 'Static 2' , 57 from dual
4 union all select 'Static 1', 66 from dual -- toggle to see the difference
5 )
6 -- This is a header which won't be displayed if table contains
7 -- type = 'Static 1' and some_id = 66
8 select 'Static 1' type, 1 some_id
9 from dual
10 where not exists (select null
11 from test
12 where type = 'Static 1'
13 and some_id = 66
14 )
15 union all
16 -- This returns actual rows (if they exist)
17 select 'Static 1' type, some_id
18 from (select some_id
19 from test
20 where type = 'Static 1'
21 and some_id = 66
22 );
TYPE SOME_ID
-------- ----------
Static 1 66
SQL>
If that does what you want, apply the same principle to the second select
you're using (to Static 2
).
Upvotes: 1