Querying from two different schema tables - sql

I have two tables - table1 and table2 - with the same columns in two different schema.
Table1
col1 | col2 | col3
-----+------+------
a1 | b1 | c1
a2 | b2 | c2
and table2
col1 | col2 | col3
-----+------+------
a1 | b1 | c1
a2 | b2 | c2
How to query from both tables (schema1.table1 and schema2.table2) so that I get the result as:
col1 | col2 | col3
-----+------+------
a1 | b1 | c1
a2 | b2 | c2
a1 | b1 | c1
a2 | b2 | c2

This looks like a simple union
select col1, col2, col3
from schema_1.table1
union all
select col1, col2, col3
from schema_2.table2

Just use union all and get the data from those two tables
SELECT col1, col2, col3 FROM schema1.dbo.table1
UNION ALL
SELECT col1, col2, col3 FROM schema2.dbo.table2

You can use the union operator.
More details regarding the union operator can be found at https://www.w3schools.com/sql/sql_union.asp

Related

SELECT values to create a unique row with optional foreign key

I have several tables in a SQL Server database, two of them (Table1 and Table2) I would like to select a specific subset from, to fill in a third table (Table3).
In Table1 there are 25 columns, from which I am only interested in three, let's call them Col1, Col2 and Col3. All three are not unique in this table, but I would like to extract the unique pairs, as follows:
Col1 + Col2 = Unique Key for Table3.
Col3 + Col2 = Optional, foreign key into Table2.
To extract the unique keys for Table3 from Table1 the following SQL works fine:
SELECT Col1, Col2
FROM Table1
GROUP BY Col1, Col2
However this is missing Col3. The first problem is that Col3 can't simply be added as part of the GROUP BY as there can be different values for it, which causes duplicate combinations of Col1 + Col2 to be returned.
This is where Table2 comes into play; Col3 + Col2 form a unique key into Table2, but not every combination is present (which is helpful), as a JOIN can be used to filter away the invalid combinations:
SELECT a.Col1, a.Col2, a.Col3
FROM Table1 a
JOIN Table2 b ON b.Col3 = a.Col3 AND b.Col2 = a.Col2
GROUP BY a.Col1, a.Col2, a.Col3
Now my final problem, unfortunately there are some (very few) combinations that do result in duplicate Col1 + Col2 keys for Table3.
If we assume it is okay to lose some Col3 values, how can I write a SELECT to extract the three columns, ensuring that the combination Col1 + Col2 is unique? And if possible keeping a Col3 value that provides a valid key combination in Table2.
I've messed about with adding TOP 1 but I've failed in getting anything to work to my liking...
EDIT: Example data as requested.
Table1
| Col1 | Col2 | Col3 |
| 100 | 00 | 010 |
| 100 | 10 | 020 |
| 200 | 00 | 030 |
| 300 | 00 | 040 |
| 300 | 00 | 040 |
| 400 | 10 | 050 |
| 400 | 10 | 060 |
| 400 | 10 | 070 |
Table2
| Colx | Col2 | Col3 |
| car | 00 | 010 |
| cat | 10 | 030 |
| dog | 00 | 040 |
| bee | 10 | 040 |
| eye | 10 | 060 |
| bit | 10 | 070 |
Table3
| Col1 | Col2 | Col3 |
| 100 | 00 | 010 |
| 100 | 10 | 020 |
| 200 | 00 | 030 |
| 300 | 00 | 040 |
| 400 | 00 | 060 |
The third table shows the result I am looking for - the table only contains unique combinations of Col1 + Col2 and also contains a Col3 values, preferably one that provides a value combination with Col2 in the second table (ie. the last entry, 400, 00, 060).
I hope this provides a little more clarity.
Maybe this way?
SELECT a.Col1, a.Col2, Max(a.Col3)
FROM Table1 a
LEFT JOIN Table2 b ON b.Col3 = a.Col3 AND b.Col2 = a.Col2
GROUP BY a.Col1, a.Col2
"The first problem is that Col3 can't simply be added as part of the GROUP BY as there can be different values for it, which causes duplicate combinations of Col1 + Col2 to be returned."
You can put the queries for different values into a select union subquery as a derived table, and group by on the derived table.

sql table comparisons - postgres

I have two tables with some columns being the same:
TABLE A
| Col1 | Col2 | Col3 |
+------+------+------+
| 1 | aa | ccc |
| 2 | null | ccc |
| null | bb | null |
TABLE B
|Col1 | Col2 | Col3| Col4 |
+------+-------+-----+------+
| 1 | aa | ccc | aaaa |
| 2 | null | ccc | cccc |
| null | bb | null | sss |
| 4 | bb | null | ddd |
I'd like to return the following:
|Col1 | Col2 | Col3| Col4 |
+------+-------+-----+------+
| 4 | bb | null | ddd |
How do I check what rows from table B are in table A and also return Col4 (from table B) where they match in the query.
I was using EXCEPT which worked great but now I need to have the outputs of Col4 in the returned query results.
Thanks.
Something like this?
SELECT Col1, Col2, Col3, Col4
FROM TableB
WHERE NOT EXISTS (
SELECT 1
FROM TableA
WHERE TableA.Col1 IS NOT DISTINCT FROM TableB.Col1
AND TableA.Col2 IS NOT DISTINCT FROM TableB.Col2
AND TableA.Col3 IS NOT DISTINCT FROM TableB.Col3
)
(Using IS NOT DISTINCT FROM to say that columns with null are equal to each other.)
The answer to your question is very easy: none of the rows from table 'A' are in table 'B'.
Those are separate tables and they have separate rows.
Now, if you want to find 'a row in table B, that has similar values in columns as a specific row in table A, you may do following:
select a.*,
case when b.ctid is null then 'I AM A VERY SAD PENGUIN AND ROW IN B WAS NOT FOUND :('
else b.col4 end as col4
from table_a a
left join table_b b on
((a.col1 = b.col1 or (a.col1 is null and b.col1 is null)) and
(a.col2 = b.col2 or (a.col2 is null and b.col2 is null)) and
(a.col3 = b.col3 or (a.col3 is null and b.col3 is null))
)
I assume that by 'similar' you would mean "if null appears in columns in both tables, the rows are still similar.
Notice the last insert into table_b i added - you are not guaranteed to find unique values of col4!:
dbfiddle, modified version of VBoka's answer
If you have no duplicates within the b table, then the following handles NULL values rather elegantly:
select col1, col2, col3, max(col4)
from ((select coll, col2, col3, null as col4, 'a' as which
from a
) union all
(select coll, col2, col3, col4, 'b' as which
from b
)
) b
group by col1, col2, col3
having min(which) = 'b';

SQL Server select column names from multiple tables

I have three tables in SQL Server with following structure:
col1 col2 a1 a2 ... an,
col1 col2 b1 b2 ... bn,
col1 col2 c1 c2 ... cn
The two first records are the same, col1 and col2, however the tables have different lengths.
I need to select the column names of the tables and the result I'm trying to achieve is the followig:
col1, col2, a1, b1, c1, a2, b2, c2 ...
Is there a way to do it?
It's possible but result's is combined into single column of three table tables.
For example
SELECT A.col1 +'/' +B.col1 +'/' + C.col1 As Col1 ,
A.col2 +'/' +B.col2 +'/' + C.col2 As col2 ,a1, b1, c1, a2, b2, c2 ,
* FROM A
INNER JOIN B
ON A.ID =B.ID
INNER JOIN C
ON C.ID = B.ID
SQL-Server is not the right tool to create a generic resultset. The engine needs to know what's coming out in advance. Well, you might try to find a solution with dynamic SQL...
I want to suggest two different approaches.
Both would work with any number of tables, as long as all of them have the columns col1 and col2 with appropriate types.
Let's create a simple mokcup scenario before:
DECLARE #mockup1 TABLE(col1 INT,col2 INT,SomeMore1 VARCHAR(100),SomeMore2 VARCHAR(100));
INSERT INTO #mockup1 VALUES(1,1,'blah 1.1','blub 1.1')
,(1,2,'blah 1.2','blub 1.2')
,(1,100,'not in t2','not in t2');
DECLARE #mockup2 TABLE(col1 INT,col2 INT,OtherType1 INT,OtherType2 DATETIME);
INSERT INTO #mockup2 VALUES(1,1,101,GETDATE())
,(1,2,102,GETDATE()+1)
,(1,200,200,GETDATE()+200);
--You can add as many tables as you need
A very pragmatic approach:
Try this simple FULL OUTER JOIN:
SELECT *
FROM #mockup1 m1
FULL OUTER JOIN #mockup2 m2 ON m1.col1=m2.col1 AND m1.col2=m2.col2
--add more tables here
The result
+------+------+-----------+-----------+------+------+------------+-------------------------+
| col1 | col2 | SomeMore1 | SomeMore2 | col1 | col2 | OtherType1 | OtherType2 |
+------+------+-----------+-----------+------+------+------------+-------------------------+
| 1 | 1 | blah 1.1 | blub 1.1 | 1 | 1 | 101 | 2019-03-08 10:53:20.257 |
+------+------+-----------+-----------+------+------+------------+-------------------------+
| 1 | 2 | blah 1.2 | blub 1.2 | 1 | 2 | 102 | 2019-03-09 10:53:20.257 |
+------+------+-----------+-----------+------+------+------------+-------------------------+
| 1 | 100 | not in t2 | not in t2 | NULL | NULL | NULL | NULL |
+------+------+-----------+-----------+------+------+------------+-------------------------+
| NULL | NULL | NULL | NULL | 1 | 200 | 200 | 2019-09-24 10:53:20.257 |
+------+------+-----------+-----------+------+------+------------+-------------------------+
But you will have to deal with non-unique column names... (This is the moment, where a dynamically created statement can help).
A generic approach using container type XML
Whenever you do not know the result in advance, you can pack the result in a container. This allows a clear structure on the side of your RDBMS and shifts the troubles how to deal with this set to the consumer.
The cte will read all existing pairs of col1 and col2
Each table's row(s) for the pair of values is inserted as XML
Pairs not existing in any of the tables show up as NULL
Try this out
WITH AllDistinctCol1Col2Values AS
(
SELECT col1,col2 FROM #mockup1
UNION ALL
SELECT col1,col2 FROM #mockup2
--add all your tables here
)
SELECT col1,col2
,(SELECT * FROM #mockup1 x WHERE c1c2.col1=x.col1 AND c1c2.col2=x.col2 FOR XML PATH('row'),TYPE) AS Content1
,(SELECT * FROM #mockup2 x WHERE c1c2.col1=x.col1 AND c1c2.col2=x.col2 FOR XML PATH('row'),TYPE) AS Content2
FROM AllDistinctCol1Col2Values c1c2
GROUP BY col1,col2;
The result
+------+------+-----------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------+
| col1 | col2 | Content1 | Content2 |
+------+------+-----------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------+
| 1 | 1 | <row><col1>1</col1><col2>1</col2><SomeMore1>blah 1.1</SomeMore1><SomeMore2>blub 1.1</SomeMore2></row> | <row><col1>1</col1><col2>1</col2><OtherType1>101</OtherType1><OtherType2>2019-03-08T11:03:49.877</OtherType2></row> |
+------+------+-----------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------+
| 1 | 2 | <row><col1>1</col1><col2>2</col2><SomeMore1>blah 1.2</SomeMore1><SomeMore2>blub 1.2</SomeMore2></row> | <row><col1>1</col1><col2>2</col2><OtherType1>102</OtherType1><OtherType2>2019-03-09T11:03:49.877</OtherType2></row> |
+------+------+-----------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------+
| 1 | 100 | <row><col1>1</col1><col2>100</col2><SomeMore1>not in t2</SomeMore1><SomeMore2>not in t2</SomeMore2></row> | NULL |
+------+------+-----------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------+
| 1 | 200 | NULL | <row><col1>1</col1><col2>200</col2><OtherType1>200</OtherType1><OtherType2>2019-09-24T11:03:49.877</OtherType2></row> |
+------+------+-----------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------+

Join two table and shows with null values

I have two tables:
Table 1
Col | Col2
--------+---------
AA | CC
Table 2
Col | Col2
--------+---------
BB | CC
Result I need
Col1 | Col2 | Col4
--------+----------+---------
AA | CC | null
null | CC | BB
I can't find any relation between two tables so, i would do :
select col as col1, col2, null as col4
from table1 t1
union all
select null, col2, col
from table2 t2;

BigQuery: Union two different tables which are based on federated Google Spreadsheet

I have two different Google Spreadsheet:
One with 4 columns
+------+------+------+------+
| Col1 | Col2 | Col5 | Col6 |
+------+------+------+------+
| ID1 | A | B | C |
| ID2 | D | E | F |
+------+------+------+------+
One with the 4 columns of the previous file, and 2 more columns
+------+------+------+------+------+------+
| Col1 | Col2 | Col3 | Col4 | Col5 | Col6 |
+------+------+------+------+------+------+
| ID3 | G | H | J | K | L |
| ID4 | M | N | O | P | Q |
+------+------+------+------+------+------+
I configured them as Federated source in Google BigQuery, now I need to create a view that will join data of both tables.
Both tables have Col1 column, which contains an ID, this ID is unique across alla the tables, does not contain replicated data.
The resulting table I'm looking for is the following one:
+------+------+------+------+------+------+
| Col1 | Col2 | Col3 | Col4 | Col5 | Col6 |
+------+------+------+------+------+------+
| ID1 | A | NULL | NULL | B | C |
| ID2 | D | NULL | NULL | E | F |
| ID3 | G | H | J | K | L |
| ID4 | M | N | O | P | Q |
+------+------+------+------+------+------+
For the columns that the first file does not have, I'm expecting a NULL value.
I'm using standardSQL, here is a statement you can use to generate a sample data:
#standardsQL
WITH table1 AS (
SELECT "A" as Col1, "B" as Col2, "C" AS Col3
UNION ALL
SELECT "D" as Col1, "E" as Col2, "F" AS Col3
),
table2 AS (
SELECT "G" as Col1, "H" as Col2, "J" AS Col3, "K" AS Col4, "L" AS Col5
UNION ALL
SELECT "M" as Col1, "N" as Col2, "O" AS Col3, "P" AS Col4, "Q" AS Col5
)
A simple UNION ALL is not working because tables have different columns
SELECT * FROM table1
UNION ALL
SELECT * FROM table2
Error: Queries in UNION ALL have mismatched column count; query 1 has 3 columns, query 2 has 5 columns at [17:1]
And wildcard operator is not a suitable way because Federated sources does not support that
SELECT * FROM `table*`
Error: External tables cannot be queried through prefix
Of course this is a sample data, with only 3-5 columns, the real tables have 20-40 columns. So an example where I need to explicitly SELECT field by field it is not a considerable way.
Is there a working way to join this two tables?
You can pass the rows through a UDF to handle the case where column names aren't aligned by position or there are different numbers of them between tables. Here is an example:
CREATE TEMP FUNCTION CoerceRow(json_row STRING)
RETURNS STRUCT<Col1 STRING, Col2 STRING, Col3 STRING, Col4 STRING, Col5 STRING>
LANGUAGE js AS """
return JSON.parse(json_row);
""";
WITH table1 AS (
SELECT "A" as Col5, "B" as Col3, "C" AS Col2
UNION ALL
SELECT "D" as Col5, "E" as Col3, "F" AS Col2
),
table2 AS (
SELECT "G" as Col1, "H" as Col2, "J" AS Col3, "K" AS Col4, "L" AS Col5
UNION ALL
SELECT "M" as Col1, "N" as Col2, "O" AS Col3, "P" AS Col4, "Q" AS Col5
)
SELECT CoerceRow(json_row).*
FROM (
SELECT TO_JSON_STRING(t1) AS json_row
FROM table1 AS t1
UNION ALL
SELECT TO_JSON_STRING(t2) AS json_row
FROM table2 AS t2
);
+------+------+------+------+------+
| Col1 | Col2 | Col3 | Col4 | Col5 |
+------+------+------+------+------+
| NULL | C | B | NULL | A |
| NULL | F | E | NULL | D |
| G | H | J | K | L |
| M | N | O | P | Q |
+------+------+------+------+------+
Note that the CoerceRow function needs to declare the explicit row type that you want in the output. Outside of that, the columns in the tables being unioned are just matched by name.
Is there a working way to join this two tables?
#standardsQL
SELECT *, NULL AS Col5, NULL AS Col6 FROM table1
UNION ALL
SELECT * FROM table2
Yo can check this using your example
#standardsQL
WITH table1 AS (
SELECT "ID1" AS Col1, "A" AS Col2, "B" AS Col3, "C" AS Col4
UNION ALL
SELECT "ID2", "D", "E", "F"
),
table2 AS (
SELECT "ID3" Col1, "G" AS Col2, "H" AS Col3, "J" AS Col4, "K" AS Col5, "L" AS Col6
UNION ALL
SELECT "ID4", "M", "N", "O", "P", "Q"
)
SELECT *, NULL AS Col5, NULL AS Col6 FROM table1
UNION ALL
SELECT * FROM table2