Insert records from 1st table to 2nd table only when the record is not present in the 2nd table - sql

I have 1 table with the same table structure as the second table, I just have to insert records from table1 to table2 with
insert into table2(select * from table1);
The table 2 has a primary key in one of the fields say(id), and some one inserted data corresponding to that primary key
table1 table2
id | name id | name
1 | new1 1 | old1
2 | new2 4 | new4
3 | new3 3 | old3
5 | new5 6 | old6
I have to insert only those records into table 2 for which the primary key is not populated.
After insertion table 2 should look like this
table 2
id | name
1 | old1
2 | new2
3 | old3
4 | new4
5 | new5
6 | old6
What is the easiest way to do this?

Use a NOT EXISTS condition to get only those rows from table1 that don't exists in table2:
insert into table2 (id, name)
select t1.id, t1.name
from table1 t1
where not exists (select *
from table2 t2
where t2.id = t1.id);

You could use MERGE statement with only INSERT WHEN NOT MATCHED:
MERGE INTO table2 t2
USING table1 t1
ON t1.id = t2.id
WHEN NOT MATCHED
THEN
INSERT INTO table2
(id, name)
VALUES
(t1.id, t1.name)

Related

Splitting up data from one table to another

Currently I have a table like shown in T1 that I'd like to split up into individual Person table like T2 and a PersonClientLink table like T3. Each relationship is stored as its own unique ID in T1. This makes duplicates of the same person and their clients which is making this difficult. I need to group the Persons from T1 into a single ID and basically turn it into T2 and create links for each relationship they have into T3. T3 Currently exists but is empty, I want to populate T3 based on the data in T1 first and then turn T1 into T2. Any advice would be appreciated :)
T1 - Current mess
ID
Client_Id
Name
1
5
Bob
2
6
Bob
3
7
Greg
4
8
Greg
T2 - Person
ID
Name
1
Bob
2
Greg
T3 - PersonClientLink
ID
Person_Id
Client_Id
1
1
5
2
1
6
3
2
7
4
2
8
I'm honestly clueless no idea where to begin with this...
I would create the T2 and T3 tables and populate them from T1. I would then drop T1 afterwards. The following is done with postgresql, but it should be the same. A serial column in postgresql is the same as an identity column in sqlserver.
create table t2 (id serial primary key,
name varchar(32) not null);
create table t3 (id serial primary key,
person_id integer not null,
client_id integer not null);
Create a foreign key from t3.person_id to t2.id
Populate t2 and t3:
insert into t2 (name) (select distinct name from t1);
insert into t3 (person_id,client_id) (
select t2.id,t1.client_id from t1,t2 where t2.name = t1.name);
Convert the join of the tables to ANSI style if sqlserver requires that.
The initial data (same as yours) and the results:
select * from t1;
id | client_id | name
----+-----------+------
1 | 5 | bob
2 | 6 | bob
3 | 7 | greg
4 | 6 | greg
(4 rows)
select * from t2;
id | name
----+------
1 | bob
2 | greg
(2 rows)
select * from t3;
id | person_id | client_id
----+-----------+-----------
1 | 1 | 6
2 | 1 | 5
3 | 2 | 6
4 | 2 | 7
(4 rows)
I hope this helps.

Update multiple columns of table based on another table sql

I have two tables:
Table1:
column1|column2|column3|column4|column5
---------------------------------------
'test1'| null | 12 |'old1' | 'gr1'
'test1'| 123 | null |'old2' | 'gr2'
'test2'| 488 | null |'old3' | 'gr3'
'test3'| 488 | null |'old4' | 'gr4'
Table2: (it's a SELECT query)
column1|column2|column4|column5
-------------------------------
'test1'| 999 | 'new1'| 'gr2'
'test3'| 1355 | 'new4'| 'gr4'
I have created the second table as a query in order to update the values of the first, where the key of the first table is (column1, column5). So the table I am after is:
Table1:
column1|column2|column3|column4|column5
---------------------------------------
'test1'| null | 12 |'old1' | 'gr1'
'test1'| 999 | null |'new1' | 'gr2'
'test2'| 488 | null |'old3' | 'gr3'
'test3'| 1355 | null |'new4' | 'gr4'
How is this done?
The exakt SQL command will of course depend on the query which produces your second table. Assuming, this query would just be "SELECT * FROM yourtable2", you can do following update command to achieve your goal:
UPDATE yourtable
SET
column2 = x.column2,
column4 = x.column4
FROM (SELECT * FROM yourtable2) x
WHERE yourtable.column1 = x.column1
AND yourtable.column5 = x.column5
Here you see this is working (in case the table "yourtable2" provides the correct data): db<>fiddle
So, you can replace the "SELECT FROM yourtable2" by your query and it will work.
Can you try
UPDATE table1 t1 set (column2,column4) = (
SELECT column2,column4
FROM table2 t2
WHERE t1.column1 = t2.column1 and t1.column5 = t2.column5
)
If you have table2 as a query, you can use WITH
WITH table2 (column1,column2,column4,column5) AS (
<your select query>
),
UPDATE table1 t1 set (column2,column4) = (
SELECT column2,column4
FROM table2 t2
WHERE t1.column1 = t2.column1 and t1.column5 = t2.column5
)

How to find the percentage of values present in one from another table in BigQuery?

table 1:
id name
1 abc
2 xyz
3 pqr
table 2:
ids loc
1 loc1
2 loc2
3 loc3
4 loc4
5 loc5
desired o/p:
table3:
match total percent
3 5 60
I have tried this:
SELECT COUNT(DISTINCT id) AS reach, COUNT(DISTINCT ids) AS total
FROM table1 RIGHT JOIN table2
ON table1.id = table2.ids
And this is giving me this which is not correct:
match total percent
3 3 100
Can someone help me in getting this correct?
SQL Fiddle
CREATE TABLE Table1 (ID int,Name varchar(10));
CREATE TABLE Table2 (ID int, Name varchar(10));
INSERT INTO `Table1` (ID,Name) VALUES (1,'abc'),(2,'xyz'),(3,'lmm'),(4,'pqr'),(5,'cde');
INSERT INTO `Table2`(ID,Name) VALUES (1,'abc'),(2,'xyz'),(3,'pqr');
Query 1:
SELECT COUNT(t2.id) AS Matching,
count(t1.ID) AS TheTotal
, (COUNT(t2.id)/count(t1.ID) *100) AS Percentage
FROM Table1 AS t1
LEFT JOIN Table2 AS t2
ON t1.ID = t2.ID
Results:
| Matching | TheTotal | Percentage |
|----------|----------|------------|
| 3 | 5 | 60 |

how to join 2 tables into one with SQL

I have 2 tables, Let's name them tb1 and tb2.
I want to add all items in tb1 that dose not exist in tb2 into new rows in tb2.
At the same time I want to update existing data in tb2 with the data in tb1, I try to understand join, merge and so on but I could not understand how doing that in SQL.
For the question I will build this 2 tables and the result I try to achieve.
tb1:
| KEY | col one | col two
+------+------------+-----------
| 1 | data one | data one
| 2 | data two | change data
| 3 | data three | data three
tb2:
| KEY | col one | col two
+------+-----------+-----------
| 1 | data one | data one
| 2 | data two | old data
| 4 | data four | some data
tb2 after SQL :
We can see we add the key 3 and we change in key 2, col 2 data
| KEY | col one | col two
+------+------------+-----------
| 1 | data one | data one
| 2 | data two | change data
| 3 | data three | data three
| 4 | data four | some data
You can generate the results you want using union all:
select t1.key, t1.col1, t1.col2
from table1 t1
union all
select t2.key, t2.col1, t2.col2
from table2 t2
where not exists (select 1 from table1 t1 where t1.key = t2.key);
Actually changing table2 is more cumbersome -- and depends on the database you are using. One method is an insert and update:
update table2
set col1 = (select t1.col1 from table1 t1 where t1.key = t2.key),
col2 = (select t1.col2 from table1 t1 where t1.key = t2.key)
where col1 <> (select t1.col1 from table1 t1 where t1.key = t2.key) or
col2 <> (select t1.col2 from table1 t1 where t1.key = t2.key);
insert into table2 (key, col1, col2)
select t1.key, t2.key, t3.key
from table1 t1
where not exists (select 1 from table2 t2 where t2.key = t1.key);
Specific databases have many methods for simplifying this logic, including on conflict, on duplicate key update, and merge commands.

Merge two rows in SQL

Assuming I have a table containing the following information:
FK | Field1 | Field2
=====================
3 | ABC | *NULL*
3 | *NULL* | DEF
is there a way I can perform a select on the table to get the following
FK | Field1 | Field2
=====================
3 | ABC | DEF
Thanks
Edit: Fix field2 name for clarity
Aggregate functions may help you out here. Aggregate functions ignore NULLs (at least that's true on SQL Server, Oracle, and Jet/Access), so you could use a query like this (tested on SQL Server Express 2008 R2):
SELECT
FK,
MAX(Field1) AS Field1,
MAX(Field2) AS Field2
FROM
table1
GROUP BY
FK;
I used MAX, but any aggregate which picks one value from among the GROUP BY rows should work.
Test data:
CREATE TABLE table1 (FK int, Field1 varchar(10), Field2 varchar(10));
INSERT INTO table1 VALUES (3, 'ABC', NULL);
INSERT INTO table1 VALUES (3, NULL, 'DEF');
INSERT INTO table1 VALUES (4, 'GHI', NULL);
INSERT INTO table1 VALUES (4, 'JKL', 'MNO');
INSERT INTO table1 VALUES (4, NULL, 'PQR');
Results:
FK Field1 Field2
-- ------ ------
3 ABC DEF
4 JKL PQR
There are a few ways depending on some data rules that you have not included, but here is one way using what you gave.
SELECT
t1.Field1,
t2.Field2
FROM Table1 t1
LEFT JOIN Table1 t2 ON t1.FK = t2.FK AND t2.Field1 IS NULL
Another way:
SELECT
t1.Field1,
(SELECT Field2 FROM Table2 t2 WHERE t2.FK = t1.FK AND Field1 IS NULL) AS Field2
FROM Table1 t1
There might be neater methods, but the following could be one approach:
SELECT t.fk,
(
SELECT t1.Field1
FROM `table` t1
WHERE t1.fk = t.fk AND t1.Field1 IS NOT NULL
LIMIT 1
) Field1,
(
SELECT t2.Field2
FROM `table` t2
WHERE t2.fk = t.fk AND t2.Field2 IS NOT NULL
LIMIT 1
) Field2
FROM `table` t
WHERE t.fk = 3
GROUP BY t.fk;
Test Case:
CREATE TABLE `table` (fk int, Field1 varchar(10), Field2 varchar(10));
INSERT INTO `table` VALUES (3, 'ABC', NULL);
INSERT INTO `table` VALUES (3, NULL, 'DEF');
INSERT INTO `table` VALUES (4, 'GHI', NULL);
INSERT INTO `table` VALUES (4, NULL, 'JKL');
INSERT INTO `table` VALUES (5, NULL, 'MNO');
Result:
+------+--------+--------+
| fk | Field1 | Field2 |
+------+--------+--------+
| 3 | ABC | DEF |
+------+--------+--------+
1 row in set (0.01 sec)
Running the same query without the WHERE t.fk = 3 clause, it would return the following result-set:
+------+--------+--------+
| fk | Field1 | Field2 |
+------+--------+--------+
| 3 | ABC | DEF |
| 4 | GHI | JKL |
| 5 | NULL | MNO |
+------+--------+--------+
3 rows in set (0.01 sec)
I had a similar problem. The difference was that I needed far more control over what I was returning so I ended up with an simple clear but rather long query. Here is a simplified version of it based on your example.
select main.id, Field1_Q.Field1, Field2_Q.Field2
from
(
select distinct id
from Table1
)as main
left outer join (
select id, max(Field1)
from Table1
where Field1 is not null
group by id
) as Field1_Q on main.id = Field1_Q.id
left outer join (
select id, max(Field2)
from Table1
where Field2 is not null
group by id
) as Field2_Q on main.id = Field2_Q.id
;
The trick here is that the first select 'main' selects the rows to display. Then you have one select per field. What is being joined on should be all of the same values returned by the 'main' query.
Be warned, those other queries need to return only one row per id or you will be ignoring data
if one row has value in field1 column and other rows have null value then this Query might work.
SELECT
FK,
MAX(Field1) as Field1,
MAX(Field2) as Field2
FROM
(
select FK,ISNULL(Field1,'') as Field1,ISNULL(Field2,'') as Field2 from table1
)
tbl
GROUP BY FK
My case is I have a table like this
---------------------------------------------
|company_name|company_ID|CA | WA |
---------------------------------------------
|Costco | 1 |NULL | 2 |
---------------------------------------------
|Costco | 1 |3 |Null |
---------------------------------------------
And I want it to be like below:
---------------------------------------------
|company_name|company_ID|CA | WA |
---------------------------------------------
|Costco | 1 |3 | 2 |
---------------------------------------------
Most code is almost the same:
SELECT
FK,
MAX(CA) AS CA,
MAX(WA) AS WA
FROM
table1
GROUP BY company_name,company_ID
The only difference is the group by, if you put two column names into it, you can group them in pairs.
SELECT Q.FK
,ISNULL(T1.Field1, T2.Field2) AS Field
FROM (SELECT FK FROM Table1
UNION
SELECT FK FROM Table2) AS Q
LEFT JOIN Table1 AS T1 ON T1.FK = Q.FK
LEFT JOIN Table2 AS T2 ON T2.FK = Q.FK
If there is one table, write Table1 instead of Table2