SQL query two queries and union - sql

I've these two approaches for a problem and they look kind of okay to me. Is there a better way to do this? Please advise.
X,Y,Z are same for both queries
Two queries and add the values:
select sum(columnA1), sum(columnA2) from tableA
where columnA3 = X and columnA4 = Y and columnA5 = Z;
select sum(columnB1) from tableB
where columnB3 = X and columnB4 = Y and columnB5 = Z;
Union All:
select sum(columnA1), sum(columnA2), sum(columbB1)
from (select columnA1, columnA2, null from tableA
where columnA3 = X and columnA4 = Y and columnA5 = Z
union all
select null, null, columnB1 from tableB
where columnB3 = X and columnB4 = Y and columnB5 = Z) unionresult

Each of your 2 options will produce the same 3 numeric results, the only real difference is in the delivery (either as 2 queries or as a single, combined, query).
I cannot really know which suits your purpose best, but you are adding a tiny overhead to get get a combined result.
Here is another possible alternative for a combined result but I don't think it's any better than the union all approach you show (& it could even be worse).
SELECT
SUM(columnA1)
, SUM(columnA2)
, (
SELECT
SUM(columnB1)
FROM tableB
WHERE columnB3 = X
AND columnB4 = Y
AND columnB5 = Z
) as sum_columnB1
FROM tableA
WHERE columnA3 = X
AND columnA4 = Y
AND columnA5 = Z
;

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 I use multiple queries inside SELECT EXISTS()?

Is it possible to write multiple queries inside the SQL EXISTS()?
Just as this example
SELECT
EXISTS (SELECT a FROM at WHERE X = :X;
SELECT b FROM bt WHERE Y = :Y;
SELECT C FROM ct WHERE Z = :Z;
)
And in case it is possible, is this the best way to check the existence of an element inside multiple tables? or using UNION ALL or JOIN would be better?
Use OR:
EXISTS (SELECT a FROM at WHERE X = :X) OR
EXISTS (SELECT b FROM bt WHERE Y = :Y) OR
EXISTS (SELECT C FROM ct WHERE Z = :Z)
This would normally be in a WHERE or CASE, not a SELECT.
You can use UNION ALL, but this is usually more efficient.

How to use union in select clause?

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

Querying speeds

In a large database, is it faster to perform a query such as
select * from table where a = 1 and b = 2 or b = 3 or b = 4;
or
select * from table where a = 1 and b = 2;
select * from table where a = 1 and b = 3;
select * from table where a = 1 and b = 4;
You should rely on the DBMS to do the optimisation for you. If the second were quicker, then the DBMS would do it that way anyway.
Go with the first (but put parentheses round the b conditions, as Tommy suggests).
As others have pointed out, the queries are not equivalent. I assume the first query should read:
select * from table where a = 1 and (b = 2 or b = 3 or b = 4);
For clarity I would suggest:
select * from table where a = 1 and b in (2, 3, 4);
In general this will perform better than asking three different queries as in the second alternative.

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