Select from union of same columns from three tables - sql

I have three tables, A, B, and C. They all hold different data, but have some columns in common.
If A, B, and C all have columns C1 and C2 then how can I look up a specific C2 value using a C1 value that could be in any of the 3 tables?
Basically, I want to do a simple look-up but have it act on the union of the 3 tables - and I'd prefer to not use a view to achieve this.
Note that this is an Ingres Vectorwise database.

You do this by doing a union of the tables in the from clause:
select c2
from ((select c1, c2 from a) union all
(select c1, c2 from b) union all
(select c1, c2 from c)
) t
where c1 = <your value>
I've used union all for performance reasons. If you are concerned about duplicate values, either use union or add a distinct in the select.
This is standard SQL and should work in any database.

I don't know what you mean by " a specific C2 value using a C1 value ",
but, whatever your query would be for the view, repeat that query and union the results,
SELECT *
FROM A
WHERE C2 = ?
UNION ALL
SELECT *
FROM B
WHERE C2 = ?
UNION ALL
SELECT *
FROM C
WHERE C2 = ?
(The view is a standard SQL feature, and will make any query you write easier.)

Related

What is functional difference between UNION and OR?

I wonder if UNION and OR in WHERE statement have any difference?
Using UNION statement with two different tables:
SELECT A.col
FROM A, B1
WHERE A.col = B1.col
UNION
SELECT A.col
FROM A, B2
WHERE A.col = B2.col
Using or in WHERE statement:
SELECT A.col
FROM A, B1, B2
WHERE A.col=B1.col or A.col=B2.col
Except the performance difference, is there any difference on their meanings?
These queries are nothing alike. First, you should learn to use proper explicit JOIN syntax.
If you ran them -- even on test tables -- you would quickly find the differences.
For instance, the union query removes duplicates. The or query does not.
The or query does a Cartesian product of the tables. So, if any of the tables is empty (such as B1 or B2) then no rows are returned. The union will return values from the other two tables.

Select full outer join from many-to-many relationships

I am trying to do something in MSSQL which I suppose is a fairly simple and common thing in any database with many-to-many relationships. However I seem to always end up with a quite complicated select query, I seem to be repeating the same conditions several times to get the desired output.
The scenario is like this. I have 2 tables (table A and B) and a cross table with foreign keys to the ID columns of A and B. There can only be one unique pair of As and Bs in the crosstable (I guess the 2 foreign keys make up a primary key in the cross table ?!?). Data in the three tables could look like this:
TABLE A TABLE B TABLE AB
ID Type ID Type AID BID
--------------------------------------------------
R Up 1 IN R 3
S DOWN 2 IN T 3
T UP 3 OUT T 5
X UP 4 OUT Z 6
Y DOWN 5 IN
Z UP 6 OUT
Now let's say I select all rows in A of type UP and all rows in B of type OUT:
SELECT ID FROM A AS A1
WHERE Type = 'UP'
(Result: R, T, X, Z)
SELECT ID FROM B AS B1
WHERE Type = 'OUT'
(Result: 3, 4, 6)
What I want now is to fully outer join these 2 sub queries based on the relations listed in AB. Hence I want all IDs in A1 and B1 to be listed at least once:
A.ID B.ID
R 3
T 3
null 4
X null
Z 6
From this results set I want to be able to see:
- Which rows in A1 does not relate to any rows in B1
- Which rows in B1 does not relate to any rows in A1
- Relations between rows in A1 and B1
I have tried a couple of things such as:
SELECT A1.ID, B1.ID
FROM (
SELECT * FROM A
WHERE Type = 'UP') AS A1
FULL OUTER JOIN AB ON
A1.ID = AB.AID
FULL OUTER JOIN (
SELECT * FROM B
WHERE Type = 'OUT') AS B1
ON AB.BID = B1.ID
This doesn't work, since some of the relations listed in AB are between rows in A1 and rows NOT IN B1 OR between rows in B1 but NOT IN A1.
In other words - I seem to be forced to create a subquery for the AB table also:
SELECT A1.ID, B1.ID
FROM (
SELECT * FROM A
WHERE Type = 'UP') AS A1
FULL OUTER JOIN (
SELECT * FROM AB AS AB1
WHERE
AID IN (SELECT ID FROM A WHERE type = 'UP') AND
BID IN (SELECT ID FROM B WHERE type = 'OUT')
) AS AB1 ON
A1.ID = AB1.AID
FULL OUTER JOIN (
SELECT * FROM B
WHERE Type = 'OUT') AS B1
ON AB1.BID = B1.ID
That just seems like a rather complicated solution for a seemingly simply problem. Especially when you consider that for A1 and B1 subqueries with more (complex) conditions - possible involving joins to other tables (one-to-many) would require the same temporary joins and conditions to be repeated in the AB1 subquery.
I am thinking that there must be an obvious way to rewrite the above select statements in order to avoid having to repeat the same conditions several times. The solution is probably right there in front me, but I just can't see it.
Any help would be appreciated.
I think you could employ a CTE in this case, like this:
;WITH cte AS (
SELECT A.ID AS AID, A.Type AS AType, B.ID AS BID, B.Type AS BType
FROM A FULL OUTER JOIN AB ON A.ID = AB.AID
FULL OUTER JOIN B ON B.ID = AB.BID)
SELECT AID, BID FROM CTE WHERE AType = 'UP' OR BType = 'OUT'
The advantage of using a CTE is that it will be compiled once. Then you can add additional criteria to the WHERE clause outside the CTE
Check this SQL Fiddle

Comma Separated list of rows of a column with group by on other columns

Below is the structure of table I have: -
Table T1
C1 C2 C3
----------
X P A
X P B
Y Q C
Y Q D
Desired output: -
C1 C2 C3
------------
X P A,B
Y Q C,D
Note: - I know i can do the same with For XML('') with group by on C1 and C2, but the main problem in my case is that the table T1 here must be a physical table object (either permanent or temp or table var or CTE) in DB. But in my case it's a derived table and when i am using the below query it's saying invalid object.
In my case it's not good to replace the derived table with temp# tables or fixed tables or even with CTE or table variable because it will take a great effort.
SELECT
b.C1, b.C2, Stuff((',' + a.C3 from t1 a where a.c1 = b.c1 for XML PATH('')),1,1,'') FROM
T1 b group by b.c1,b.c2
I did not have T1 as fixed table. Please consider it as derived table only.
I need the solution with existing derived table.
Please help.
Below is the query with derived table: -
Please consider this only as a demo query. It's not as simple as given below and a lot of calculations have done to get the derived tables and 4 levels of derived tables have been used.
SELECT C1, C2, Stuff((',' + a.C3 from A B where a.c1 = b.c1 for XML PATH('')),1,1,'')
FROM
(
SELECT C1, C2, C3 FROM T1 WHERE C1 IS NOT NULL--and a lot of calculation also
)A
Please mind that T1 is not just below one step, in my case T1 the actual physical table is 4 level downs by derived tables.
If you can post the query the produces derived table, we can help you work it out, but as of the moment try substituting table1 with the derived query.
;WITH Table1
AS
(
SELECT C1, C2, C3 FROM T1 WHERE C1 IS NOT NULL--and a lot of calculation also
)
SELECT
C1,C2,
STUFF(
(SELECT ',' + C3
FROM Table1
WHERE C1 = a.C1 AND C2 = a.C2
FOR XML PATH (''))
, 1, 1, '') AS NamesList
FROM Table1 AS a
GROUP BY C1,C2
SQLFiddle Demo

Access SQL Query to search value in 2 tables but use just one?

I have 2 tables in MS Access and need to query them looking for a value. If the value is in A, then use that. If value is in B, then use that. If the value is in both tables, then use only the value from table A.
How can I make a query to do that?
Thanks!
How about:
SELECT IIF(IsNull(AField),(SELECT AField FROM Table2 WHERE ID=16), AField)
FROM Table1
WHERE ID=16
If you want to do an entire table rather than 1 row :-
select C1, C2 from TableA where C2 is not null
union all
select C1, C2 from TableB where C1 in ( select c1 from TableA where C2 is null )

Reference subquery several times

Simplified version of the statement I try to run (a, b, and m are tables with only one column containing integers):
SELECT * FROM m WHERE
c1 IN (SELECT * FROM a) OR
c1 IN (SELECT * FROM b)
AND (NOT c1 IN (SELECT * FROM a)
OR c1 IN (SELECT * FROM b));
I know this could be done more easily, but I have to keep this structure (i.e. cannot JOIN for instance). How could I avoid repeating the subqueries after the AND NOT, since they will return the same set as the previous ones?