Merging two tables into new table by ID and date - sql

Let' say I have two tables:
table 1:
col a | col b | col c
1 | 62215 | 21
1 | 62015 | 22
2 | 62215 | 23
2 | 51315 | 24
and table 2:
col a | col b| col f
1 | 62015| z
1 | 62215| x
2 | 51315| y
2 | 62215| t
Where neither column a and column b are unique on their own, but the pairs (col a, col b) are all unique. How would I go about merging these two tables, to produce a
Table 3:
col a | col b| col c | col f
I want to combine these tables together, into one big table. So the new table has the values from column a and b from both tables, along with the columns unique to either table 1 or two.
I'm sure this is an extremely simple problem using MERGE or UNION but I don't use SQL at all, so I don't know how it would look like.
Thank you.

You can use a SELECT statement when inserting into a table. What I would do here is write a select statement that pulls all of the columns you need first. You will have to do a full outer join (simulated by a union of left and right joins) because some pairs may exist in one table but not the other. The select would look like this:
SELECT t1.colA, t1.colB, t1.colC, t2.colF
FROM tab1 t1
LEFT JOIN tab2 t2 ON t2.colA = t1.colA AND t2.colB = t1.colB
UNION
SELECT t1.colA, t1.colB, t1.colC, t2.colF
FROM tab1 t1
RIGHT JOIN tab2 t2 ON t2.colA = t1.colA AND t2.colB = t1.colB;
Then, to insert into table 3:
INSERT INTO tab3 (mySelect);
Here is an SQL Fiddle example.
Note that for the pairs that exist in one table and not the other, you will get NULL values. For example, if a row exists in table 1 and not table 2, colF will be null in table 3.

I'm not sure if I understand the data. Are you saying that colA and colB are unique across both tables? do you want to join or union?
As a union:
Select `col a`,`col b`, `col c`, null
from `table 1`
union
Select `col a`,`col b`, null, `col f`
from `table 2`
As a join:
Select `table 1`.`col a`,`table 1`.`col b`,`table 1`.`col c`,`table 2`.`col f`
from `table 1` join `table2`
on `table 1`.`col a` = `table 1`.`col a`
on `table 1`.`col b` = `table 1`.`col b`
to insert into a table put
insert into `table 3`
in front of it.
I hope this helps.
The union would produce 1 record for every record in each of table 1 and 2. A join will combine the data if col a and col b are the same in both tables. I think the latter is what you want. I didn't use a union all because that might create duplicates.

Related

Select data in tables by conditions between 2 tables which is not linked

I have a large select with a lot of inner joins.
In the select I have an array_agg function for one set of data.
This array contains only a column of a table, but now I want to append at the end of the array data from another table. The data I need to add is not directly linked with the previous table where I need the column.
Query example:
select
origin_table.x,
origin_table.y,
array_agg(table1.data) ...
from
origin_table
inner join ... inner join ... full join table1 on
table.origin_table_id = origin_table.id ...
group by
...
Result array:
ID 1: example_data, {baba, bobo}
ID 2: example_data, {bibi, bubu}
Example of my tables:
table 1:
id | data | origin_table_id
----+---------+----------
1 | baba | 1
2 | bobo | 1
3 | bibi | 2
4 | bubu | 2
table 2:
id | data_bis
---+---------
1 | byby
2 | bebe
origin table:
id | table2_id
---+----------
1 | 2
2 | 1
Expected result with the 3 tables:
ID 1: example_data, {baba, bobo, bebe}
ID 2: example_data, {bibi, bubu, byby}
But got :
ID 1: example_data, {baba, bobo, bebe, byby}
ID 2: example_data, {bibi, bubu, bebe, byby}
What I need is:
How to have all the data of table 1 which respect the condition and append to it the unique table 2 data but not all elements of the table.
Try below query..
create table tab1 (id integer,data character varying,origin_table_id integer);
insert into tab1
select 1,'baba',1
union all
select 2,'bobo',1
union all
select 3,'bibi',2
union all
select 4,'bubu',2
create table tab2 (id integer,data_bis character varying);
insert into tab2
select 1,'byby'
union all
select 2,'bebe'
create table OriginalTable (id integer,table2_id integer);
insert into OriginalTable
select 1,2
union all
select 2,1
select * from OriginalTable
select origin_table_id,data
from tab1
union all
select OriginalTable.table2_id,data_bis
from OriginalTable
join tab2 on tab2.id = OriginalTable.id
order by origin_table_id
Result:
1;"baba"
1;"bobo"
1;"bebe"
2;"bibi"
2;"bubu"
2;"byby"
I can give you some idea and sample code to achieve your requirement.
First you can UNION ALL table 'table 1' and 'table 2' using the relation table 'origin table'.
WITH CTE
AS
(
SELECT AA.id,AA.data_bis,AA.origin_table_id
FROM table_1 AA
UNION ALL
SELECT NULL id, A.data_bis,B.id origin_table_id
FROM table_2 A
INNER JOIN origin_table B
ON A.id = B.table2_id
)
SELECT * FROM CTE
After applying UNION ALL, data will be looks like below-
data_bis origin_table_id
baba 1
bobo 1
bibi 2
bubu 2
byby 2
bebe 1
Now you can apply 'string_agg' on your data as below-
SELECT origin_table_id,string_agg(DISTINCT data_bis,',')
FROM CTE
GROUP BY origin_table_id
And the output will be-
origin_table_id string_agg
1 baba,bebe,bobo
2 bibi,bubu,byby
Now, you can apply further JOINING to this data as per your requirement. You can check DEMO HERE
Please keep in mind hat this is not exact solution of your issue. Just idea...

get name of tuples that match an entire column in another table

I have to select every name from table1 where there's tuples that match every type from table2 without grouping or aggregate functions.
table1 table2
name|type type|info
a | 1 1 | .
a | 2 2 | ..
a | 3 3 | ...
b | 1
b | 2
b | 3
c | 2
From here, it should output
name|
a |
b |
edit:
ended up doing something like
SELECT distinct outside.name
FROM table1 outside
WHERE '' NOT IN
[ (SELECT *
FROM table1 t
WHERE t.name=outside.name)
RIGHT OUTER JOIN
table2 ]
Second select makes a table with empty values for names that don't have a type in table2. So if '' isn't in the second select that means it has a tuple for every type in table2. I think
Here is one method:
select t1.name
from table1 t1
where exists (select 1 from table2 t2 where t2.type = t1.type)
group by t1.name
having count(distinct t1.type) = (select count(distinct t2.type) from table2);
This filters t1 down to the matches in t2. It then counts the number that match.
This uses count(distinct), which allows duplicates in the respective tables. If there are no duplicates, then just use count().

dynamic selection in SQL aggregate function

Imagine I have a column with row data A, B, and C. When aggregating the column, I want B to show up if any row contains B, else C, else A.
Is this possible? I'm using vertica but would be curious to hear solutions for other data stores.
+------+-------+
| Col1 | Col 2 |
+------+-------+
| A | X |
| B | X |
| C | X |
+------+-------+
SELECT ???(Col1), Col2
FROM my_two_column_table
GROUP BY Col2
expected result: one row - B, X
Something like this could work:
SELECT COALESCE( MAX(t2.value), MAX(t3.value), MAX(t4.value) )
FROM my_table t1
LEFT OUTER JOIN my_table t2 ON t2.value = 'B'
LEFT OUTER JOIN my_table t3 ON t3.value = 'C'
LEFT OUTER JOIN my_table t4 ON t4.value = 'A'
WHERE t1.value in ( 'A', 'B', 'C' )
The t1 table can also be replaced by dual or whatever dummy table with at least one row you have.

Finding field value pairs using SQL

I have difficulties summarizing the issue into a nice, neat title, so the title may be misleading. Here is the situation
Table 1 has an ID, an Issue, and a resolution date, so it is expected that some dates will be null. ID's can be assigned to multiple issues as well.
Table_1:
ID | Issue | Date
1 | a | 1/1
2 | a | 1/1
3 | b |
4 | c | 1/2
I use another table to update this table, so for this example, the data in table_2 looks like:
ID | Issue | Date
3 | b | 1/3
1 | b | 1/3
Now, I have one query which will update table_1 dates using table_2 information, based on the ID/Issue pairing, using something like this:
Update Table_1 tab1
left outer join Table_2 tab2
on tab1.id = tab2.id and tab1.issue = tab2.issue
set tab1.date = tab2.date
However, there will be times where table 2 has ID/Issue pairs that are not in table_1. I would like to instead insert those rows into table_1, but I'm not sure how to do this.
If it was just one single field, say ID, i could just do something like:
insert into table_1 (ID, Issue, Date)
select ID, Issue, Date
from table_2 where table_2.ID not in (select ID from table_1)
How would I do this for an ID/Issue pairing?
Using the above example, I would want to insert the following row from table_2 into table_1:
1 | b | 1/3
since an ID/Issue pair of 1/b exists in table 2 but not table 1.
How would I go about selecting from table 2 the id/issue pairs that do not exist in table 1?
You can use a left outer join to do this:
insert into table_1 (ID, Issue, Date)
select ID, Issue, Date
from table_2 t2
left outer join table_1 t1 on t1.ID = t2.ID and
t1.Issue = t2.Issue
where t1.ID is null
This guarantees you to get every row in table_2 and then limit the rows in table two if there isn't a match in table_1.
One method is to use not exists:
insert into table_1 (ID, Issue, Date)
select ID, Issue, Date
from table_2
where not exists (select 1
from table_1
where table_2.ID = table_1.ID and table_2.issue = table_1.issue
);

SELECT Table From Other Table

how to select table from select other table ?
Table1
ID| Name |
1 | Henry
2 | Dony
Table2
ID| Addres|
1 | London
2 | Texas
I have select ID table2 From Select table1, like below :
SELECT ID From Table2 Where Select ID From Table1
You could write a JOIN to do so:
SELECT ID FROM Table2 AS T2
INNER JOIN Table1 AS T1
ON T2.ID=T1.ID
Christos is totally right, you can just use an INNER JOIN to join the two tables. Basically, what this will do is combine both tables, returning only those values from where your specified match key exists. So if you have an ID from table 1, and it isn't in table 2, then you won't see that ID in the query Christos specified. You can use a LEFT JOIN on the command above to get ALL ID's from the T1 table (or a RIGHT JOIN to get all ID's from T2).
Good luck!