Finding field value pairs using SQL - 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
);

Related

SQL - How to pick the best available value for each column for each ID from multiple tables?

I have two tables with the same variables referring to attributes of a person.
How can I combine data from two such tables picking the best available value for each column from each table for each field?
Requirements:
For each field, I would like to fill it with a value from either one of the tables, giving a preference to table 1.
Values can be NULL in either table
In the combined table, the value for column 1 could come from table 2 (in case table 1 is missing a value for that person) and the value for column 2 could from table 1 (because both tables had a value, but the value from table 1 is preferred).
In my real example, I have many columns, so an elegant solution with less code duplication would be preferred.
Some users may exist in only one of the tables.
Example:
Table 1:
user_id | age | income
1 | NULL| 58000
2 | 22 | 60000
4 | 19 | 35000
Table 2:
user_id | age | income
1 | 55 | 55000
2 | 19 | NULL
3 | 22 | 33200
Desired output:
user_id | age | income
1 | 55 | 58000
2 | 22 | 60000
3 | 22 | 33200
4 | 19 | 35000
I think that's a full join and priorization logic with colaesce():
select user_id,
coalesce(t1.age, t2.age) as age,
coalesce(t1.income, t2.income) as income
from table1 t1
full join table2 t2 using(user_id)
Use full outer join if user_id in each table is unique.
SELECT
COALESCE(t1.user_id, t2.user_id) AS user_id,
GREATEST(t1.age, t2.age) AS age,
GREATEST(t1.income, t2.income) AS income
FROM t1
FULL OUTER JOIN t2 ON t1.user_id = t2.user_id
try like below using coalesce()
select t1.user_id, coalesce(t1.age,t2.age),
t1.income>t2.income then t1.income else t2.income end as income
table1 t1 join table2 t2 on t1.usesr_id=t2.user_id
You can use below code:
With TableA(Id,age,income) as
( --Select Common Data
select table_1.id,
--Select MAX AGE
case
when table_1.age> table_2.age or table_2.age is null then table_1.age else table_2.age
end,
--Select MAX Income
case
when table_1.income>table_2.income or table_2.income is null then table_1.income else table_2.income
end
from table_1 inner join table_2 on table_2.id=table_1.id
union all
-- Select Specific Data of Table 2
select table_2.id,table_2.age,table_2.income
from table_2
where table_2.id not in (select table_1.id from table_1)
union all
-- Select Specific Data of Table 1
select table_1.id,table_1.age,table_1.income
from table_1
where table_1.id not in (select table_2.id from table_2)
)select * from TableA

SQL Join On Columns of Different Length

I'm trying to join two tables together in SQL where the columns contain a different number of unique entries.
When I use a full join the additional entries in the column joined on are missing.
The code I'm using is (in a SAS proc SQL):
proc sql;
create table table3 as
select table1.*, table2.*
from table1 full join table2
on table1.id = table2.id;
quit;
Visual example of problem (can't show actual tables as contain sensitive data)
Table 1
id | count1
1 | 2
2 | 3
3 | 2
Table 2
id | count2
1 | 4
2 | 5
3 | 6
4 | 2
Table 3
id | counta | countb
1 | 2 | 4
2 | 3 | 5
3 | 2 | 6
- | - | 2 <----- I want don't want the id column to be blank in this row
I hope I've explained my problem clearly enough, thanks in advance for your help.
The id from table 1 is blank because the row from table2 has no match in table 1. Try looking at the output from this query:
select coalesce(table1.id, table2.id) as id, table1.count1, table2.count2
from table1 full join table2
on table1.id = table2.id;
Coalesce works from left to right returning the first non null value (it can take more than 2 arguments). If the id in table 1 is null it uses the id from table 2 instead
I recommend also to alias all tables in queries, so I’d have written this:
SELECT
COALESCE(t1.id, t2.id) as id,
t1.count1,
t2.count2
FROM
table1 t1
FULL OUTER JOIN
table2 t2
ON
t1.id = t2.id;
Simply select coalesce(t1.id, t2.id), will return the first non-null id value.

does LEFT JOIN return same row count as left table?

SELECT *
FROM t1
LEFT JOIN t2 ON t1.fk = t2.id;
Will it always return the same row count as that of t1 ?
The contract of a left join states that, in the absence of a WHERE clause which might remove records from the result set, all records which appear in the left side of the join will appear at least once. Consider the following data set:
t1
id | fk
1 | 1
2 | 2
t2
id | value
1 | 1
1 | 2
Your query would return this result set:
id | fk | id | value
1 | 1 | 1 | 1
1 | 1 | 1 | 2
2 | 2 | NULL | NULL
Note carefully that the first table's fk = 2 did not match anything to the second table. This record still appears in the result set, but all columns coming from the second table are NULL. Also, note that fk = 1 records appear twice, because that single record in the first table matched twice to the second table.
If t2.id has a unique constraint, the row count will always be the same as if the join isn't there. If it's not unique, you will get multiple duplicates of the same t1 row, each with its own corresponding t2 row. Whether that's good enough for you depends on your database design.
Will it always return the same row count as that of t1?
No.
A LEFT JOIN is a join and as such will match one row from one table to multiple rows of another table. The result set may have the same number of rows or more rows.
Not necessarily:
CREATE TABLE t1(id int, fk int);
INSERT INTO t1 VALUES (1,1);
CREATE TABLE t2(id int, value int);
INSERT INTO t2 VALUES(1,1),(1,2);
SELECT *
FROM t1
LEFT JOIN t2 ON t1.fk = t2.id;
returns 2 rows:
id fk id value
1 1 1 1
1 1 1 2

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().

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!