How to use union in select clause? - sql

I have two tables (created here for example) like:
X1 Y1
a 1
b 2
c 3
d 4
and
X2 Y2
a 5
m 6
n 7
b 4
And I want the output column:
X Y1 y2
a 1 5
b 2 4
c 3 0
d 4 0
m 0 6
n 0 7
What I tried is:
SELECT (A.X1 UNION B.X1) AS X, A.Y1,B.Y2
FROM A FULL OUTER JOIN B
ON A.X1 = B.X2
(the query mentioned above is just sample).
After executing this query I am getting error message:
Syntax error: near UNION in select clause
Can someone tell me what is wrong here. Is there any other option to get the output table in the mentioned format?

union is used to join results one after another. You're attempting to join results side by side (which you already did!). The only thing you're missing is a coalesce call to handle the missing values:
SELECT COALESCE(a.x1, b.x2) AS x,
COALESCE(a.y1, 0) AS y1,
COALESCE(b.y2, 0) AS y2
FROM a
FULL OUTER JOIN b on a.x1 = b.x2

You can try COALESCE
The COALESCE function returns the first of its arguments that is not
null. Null is returned only if all arguments are null.
SELECT COALESCE(A.X1,B.X2) AS X, COALESCE(A.Y1, 0) AS Y1, COALESCE(B.Y2, 0) AS Y2
FROM A FULL OUTER JOIN B
ON A.X1 = B.X2

SELECT Coalesce(a.x1,b.x1) AS X, coalesce(a.y1,0) as Y1 coalesce(b.y2,0) as Y2
FROM a
FULL OUTER JOIN
b ON a.x1 = b.x2
You don't need the UNION statement here, the union is used to add a resultset from a select to a resultset from a different select
You just need to use your join here with the correct on statement (which you did correct) and get the x1 or x2 from one of the tables as x1 would be equal to x2 within the same row
EDIT: Added coalesce statements to my query to return value for x if a.x1 does not exist but b.x2 does exist, also added 0 if a field doesn't exist for y1 or y2

The error is because UNION is not command that can be used in the list of columns, it is on set level, you can UNION two selects like:
SELECT * FROM table1
UNION
SELECT * FROM table2
they just need to have same columns

Related

"SELECT column ... WHERE", knowing value of other column, can't use subquery

I'm working on this SELECT query:
SELECT * FROM x
JOIN y ON x.struktorg = y.ref
WHERE y.rodzic = (SELECT ref FROM y WHERE y.symbol = 'the value i know')
The goal is to not use subselect. I know the value of symbol column, but the table that I need to get results from doesn't use it. It uses the reference number of that value.
you can join to y one more time:
SELECT * FROM x
JOIN y y1 ON x.struktorg = y1.ref
join y y2
ON y1.rodzic = y2.ref
and y2.symbol = 'the value i know'
but I don't see any benefit using join over subquery in this scenario .
if the subquery table y is the same of the JOIN y, then you can do this
SELECT *
FROM x
JOIN y ON x.struktorg = y.ref and y.rodzic = y.ref and y.symbol = 'the value i know'
if the subquery table y is diferent of the JOIN y, then you can do this renaming subquery table y for z
SELECT * FROM x
JOIN y ON x.struktorg = y.ref
JOIN z ON y.rodzic = z.ref and z.symbol = 'the value i know'
I would go around the sub-select by creating a temporary table first, like in the example below:
SELECT ref INTO #TEMP_TABLE FROM y WHERE y.symbol = 'the value i know'
Then I would join on that temporary table I created like in the example here:
SELECT * FROM x
JOIN y ON x.struktorg = y.ref
JOIN #TEMP_TABLE z on z.ref = y.rodzic
Having said that, I am sure that the above solution works effectively for SQL Server. However, I've never used Firebird, so the principles there might be different.

Can this be made into a sql join

I want to find where mydata has a Q value but not at least one corresponding d value. How would I solve using a left join or right join?
If it can not be solved using joins, please give some insight into why not, because I am not seeing it.
Below is the solution that I found which works against data provided.
SELECT distinct tablea.mykey
FROM mytest as tablea
where tablea.mydata = 'Q'
and tablea.mykey not in (select distinct tableb.mykey
FROM mytest as tableb
where tableb.mydata = 'd')
mykey mydata
7 d
5 Q
5 d
5 d
6 Q
6 d
6 a
9 Q
9 a
9 a
You can use an outer join and then select only the non-matches
SELECT distinct tablea.mykey
FROM mytest as a
left join mytest as b on a.mykey = b.mykey
and b.mydata = 'd'
where a.mydata = 'Q'
and b.mykey is null

Execute query for each pair of values from a list

I have a list of value pairs over which I iterate and run a query, the skeleton of which could be thought of like this.
list of pairs - ((x1,y1), (x2,y2), ... (xn,yn)) xi, yi are not all distinct.
q is an oracle query which returns a single value for any (xi,yi)
global_table is a single row table with
id col deleted
1 Y NULL
A few rows from 'table':
id col deleted pid did
1 NULL Y 25 1
81 N NULL NULL 149
101 Y NULL 22 149
61 Y NULL NULL NULL
Also, there is a UNIQUE constraint on (pid, did, deleted) in table.
The query q goes like this.
select w.finalcol from
(select coalesce(a.col,b.col,c.col,d.col) as finalcol from
(select * from global_table where deleted is null) a
left outer join
(select * from table where deleted is null) b
on b.pid is null and b.did is null
left outer join
(select * from table where deleted is null) c
on c.pid is null and c.did = xi
left outer join
(select * from table where deleted is null) d
on d.pid = yi and d.did = xi
) w
n = 60
n is determined by another query which returns the list of value pairs.
for element in (list of pairs)
q(xi,yi) (xi and yi might be used any number of times in the query)
I am trying to reduce the number of times I run this query. (from n times to 1)
I can try passing the individual lists and to the query after isolating them from the list of pairs but the catch is that not all pairs are present in the table(s) being queried from. But, you do get a value from the table for pairs that dont exist in the table(s) since there is a default case at play here (not important).
The default case is when
select * from table where deleted is null
and c.pid is null and c.did = xi
select * from table where deleted is null
and c.pid = yi and c.did = xi
dont return any rows.
I want my result to be of the form
x1 y1 q(x1,y1)
x2 y2 q(x2,y2)
.
.
.
xn yn q(xn,yn)
(no pair must be left out, given that a few pairs might actually not be in the table)
How do I achieve this using just a single query?
Thanks

Searching Multiple Rows at a time through a single SQL query

I have a table whose data is in this manner.
A B C
---------
0 6 2
0 3 4
1 0 2
1 1 4
I wrote a SQL query -
select A
from Table
where (B = 6 and C = 2) AND (B = 3 and C = 4).
Obviously it returned zero results since this query would search in the same row. Please help me with writing a better one to produce results such that it can check two rows with a single statement.
EDIT:
I am not looking for 'OR' statement. I need to find an element of A such that it has two corresponding rows AND each of the rows has elements 6,2 and 3,4 present in columns B,C correspondingly.
PS.
(I don't have the option of writing two queries and then finding the common elements of two set.)
Many thanks in advance
I guess you want something like this
select A
from YourTable
where (B = 6 and C = 2) or
(B = 3 and C = 4)
group by A
having count(distinct B) >= 2
Try here:
https://data.stackexchange.com/stackoverflow/q/123711/
Use OR instead of AND
select A from Table where (B=6 and C=2) OR (B=3 and C=4).
If you want the onlu result use DISTINCT
select DISTINCT A from Table where (B=6 and C=2) OR (B=3 and C=4).
If you need to check the equality of A, use this:
select t1.A
from Table t1
JOIN Table t2 ON t1.A = t2.A
where T1.B=6 and t1.C=2 AND t2.B=3 and t2.C=4
As you see - using AND again
Are you trying to get this??
SELECT A
FROM Table
WHERE (B = 6 AND C = 2) OR (B = 3 AND C = 4)
This would return the A column for all four rows again.
If not: WHAT exactly are you trying to select?
IF you want just two rows, one with A = 0, one with A = 1, then use DISTINCT:
SELECT DISTINCT A
FROM Table
WHERE (B = 6 AND C = 2) OR (B = 3 AND C = 4)
Maybe:
select A
from Table
where (B = 6 and C = 2)
INTERSECT
select A
from Table
(B = 3 and C = 4)

SQL Where to filter on Nested query

I have a query that looks like this:
Insert Into tblX (a,b,c)
Select x as a, y as b
(select top 1 whatever from tblZ as z where z.aID = y.aID order by z.s desc) as c
from tblY as y
where y.foo = 'bar'
AND c <> NULL
The problem is that last line.
It tells me that c is an invalid column name. using y.c as well, to the same result.
I need to not inset rows where that giant inner query is null, because tblX cannot accept nulls there. I feel like I should be able to filter on that column, but I can't quite get the syntax right.
You will probably need to double-nest this query.
Also, depends on your DBMS, but you should be checking C IS NOT NULL
You are using two tables without a join. If you tell us what you are trying to achieve, we can help better.
What ended up working is double nesting the query.
Insert Into tblX (a,b,c)
Select a,b,c from
(select x as a,
y as b,
(select top 1 whatever from tblZ as z where z.aID = y.aID order by z.s desc) as c
from tblY as y where y.foo = 'bar') as foobar
Where c IS NOT NULL