Inserting unique value from another table - sql

Tables: I have 3 tables
They are cust, new_cust, old_cust
all of them have 3 columns, they are id, username, name
each of them have possibilities to have same data as the others.
I would like to make "whole" table that consisting all of them but only the uniques.
I've Tried
Creating a dummy table
I've tried to create the dummy table called "Temp" table by
select *
into Temp
from cust
insert all table to dummy
Then I insert all of them into they Temp table
insert into temp
select * from new_cust
insert into temp
select * from old_cust
taking uniques using distinct
After they all merged I'm using distinct to only take the unique id value
select distinct(id), username, fullname
into Whole
from temp
it did decreasing some rows
Result
But after I move it to whole table I would like to put primary key on id but I got the message that there are some duplicate values. Is there any other way?

I am guessing that you want unique ids. And you want these prioritized by the tables in some order. If so, you can do this with union all and row_number():
select id, username, name
from (select c.*,
row_number() over (partition by id order by priority) as seqnum
from ((select id, username, name, 1 as priority
from new_cust
) union all
(select id, username, name, 2 as priority
from cust
) union all
(select id, username, name, 3 as priority
from old_cust
)
) c
) c
where seqnum = 1;

Try this:
insert into temp
select * from new_cust
UNION
select * from old_cust
Union will avoid the duplicate entries and you can then create a primary key on ID column

Try this below query...
WITH cte as (
SELECT id, username, NAME,
ROW_NUMBER() OVER (PARTITION BY t1.id ORDER BY t1.username, t1.name ) AS rn
FROM cust t1
LEFT JOIN new_cust t2 ON t1.Id = t2.Id
LEFT JOIN old_cust t3 ON t2.Id = t3.Id
)
SELECT id, username, NAME
FROM cte
WHERE rn = 1
Note:-
Put all the query inside a CTE(Common table expression)
with a new column(rn) that you will use to filter the results.
This new Column will produce ROW_NUMBER()....PARTITION BY username,name.....

But after I move it to whole table I would like to put primary key on
id but I got the message that there are some duplicate values.?
That's because You are trying to insert ID value from each of the tables to Whole table.
Just insert username and name and skip ID. ID is IDENTITY and it MUST be unique.
Run this on Your current Whole table to see if You have duplicated Id's:
select COUNT(ID), username
from whole
GROUP BY username
HAVING COUNT(ID) > 1
To get unique customers recreate table Whole and make ID col IDENTITY:
IF OBJECT_ID ('dbo.Whole') IS NOT NULL DROP TABLE dbo.Whole;
CREATE TABLE Whole (ID INT NOT NULL IDENTITY(1,1), Name varchar(max), Username varchar(max))
Insert values into Whole table:
INSERT INTO Whole
SELECT Name, Username FROM cust
UNION
SELECT Name, Username FROM new_cust
UNION
SELECT Name, Username FROM old_cust
Make ID col PK.

What does Unique mean for your row ?
If it is only the username, and you don't care about keeping the old ID values,
this will favor the new_cust data over the old_cust data.
SELECT
ID = ROW_NUMBER() OVER (ORDER BY all_temp.username)
, all_temp.*
INTO dbo.Temp
FROM
(
SELECT nc.username, nc.[name] FROM new_cust AS nc
UNION
SELECT oc.username, oc.[name]
FROM old_cust AS oc
WHERE oc.username NOT IN (SELECT nc1.username FROM new_cust AS nc1) --remove the where part if needed
) AS all_temp
ALTER TABLE dbo.Temp ALTER COLUMN ID INTEGER NOT NULL
ALTER TABLE dbo.Temp ADD PRIMARY KEY (ID)
If by Unique you mean both the username and name then just remove the where part in the union

Related

Insert/join table on multiple conditions

I’ve a table that looks like this:
Table A
Version,id
5060586,22285
5074515,22701
5074515,22285
7242751,22701
7242751,22285
I want to generate a new key called groupId that is inserted as my example below:
Table A
Version,id,groupId
5060586,22285,1
5074515,22701,2
5074515,22285,2
7242751,22701,2
7242751,22285,2
I want the groupId to be the same as long as the id's are the same in the different versions. So for example version 5074515 and 7242751 has the same id's so therefor the groupId will be the same. If all the id's aren't the same a new groupId should be added as it has in version 5060586.
How can i solve this specific problem in SQL oracle?
One approach is to create a unique value representing the set of ids in each version, then assign a groupid to the unique values of that, then join back to the original data.
INSERT ALL
INTO t (version,id) VALUES (5060586,22285)
INTO t (version,id) VALUES (5074515,22701)
INTO t (version,id) VALUES (5074515,22285)
INTO t (version,id) VALUES (7242751,22701)
INTO t (version,id) VALUES (7242751,22285)
SELECT 1 FROM dual;
WITH groups
AS
(
SELECT version
, LISTAGG(id,',') WITHIN GROUP (ORDER BY id) AS group_text
FROM t
GROUP BY version
),
groupids
AS
(
SELECT group_text, ROW_NUMBER() OVER (ORDER BY group_text) AS groupid
FROM groups
GROUP BY group_text
)
SELECT t.*, groupids.groupid
FROM t
INNER JOIN groups ON t.version = groups.version
INNER JOIN groupids ON groups.group_text = groupids.group_text;
dbfiddle.uk
You can use:
UPDATE tableA t
SET group_id = ( SELECT COUNT(DISTINCT id)
FROM TableA x
WHERE x.Version <= t.version );
Which, for the sample data:
CREATE TABLE TableA (
Version NUMBER,
id NUMBER,
group_id NUMBER
);
INSERT INTO TableA (Version, id)
SELECT 5060586,22285 FROM DUAL UNION ALL
SELECT 5074515,22701 FROM DUAL UNION ALL
SELECT 5074515,22285 FROM DUAL UNION ALL
SELECT 7242751,22701 FROM DUAL UNION ALL
SELECT 7242751,22285 FROM DUAL;
Then, after the update:
SELECT * FROM tablea;
Outputs:
VERSION
ID
GROUP_ID
5060586
22285
1
5074515
22701
2
5074515
22285
2
7242751
22701
2
7242751
22285
2
db<>fiddle here

Copy A table to another Table in PostgreSQL

I have two Table
one is student_record_temp
id
name
roll
1
Shadman
2
2
Adnan
3
Now I want to copy the row in student_record where the name is shadman and it returns both student_record_temp and student_record id
I am trying to solve this in
INSERT INTO student_record (name,rool) select name,roll from student_record_temp
FROM student_record_temp WHERE name='shadman' RETURNING student_record.id,student_record_temp.id
ERROR: missing FROM-clause entry for table "student_record_temp"
LINE 8: student_record.id,student_record_temp.id
but I got an error and how I can solve this.
To copy a table with partial data from an existing table
CREATE TABLE new_table AS
SELECT
*
FROM
existing_table
WHERE
condition;
The condition in the WHERE clause of the query defines which rows of the existing table will be copied to the new table
or you can use this:
INSERT INTO TABLE1 (id, col_1, col_2, col_3)
SELECT id, 'data1', 'data2', 'data3'
FROM TABLE2
WHERE col_a = 'something';
You can't be returning data from select in the insert query. You can use two scenarios:
second scenario
If name column data from student_record_temp table is unique. you can use join in returning query:
insert into student_record as sr (name, roll)
select srt.name, srt.roll
from student_record_temp srt
where name = 'shadman'
returning sr.id, (select id from student_record_temp r_srt where r_srt.name = sr.name);
first scenario
If name column data from student_record_temp table is not unique. you have to create temp unique field and use from that
with select_data as (
select srt.id, srt.name, srt.roll, row_number() OVER (ORDER BY id) AS rn
from student_record_temp srt
where name = 'shadman'),
add_data as (
insert into student_record as sr (name, roll)
select sd.name, sd.roll
from select_data sd
order by sd.id
returning sr.id)
select ad.id as insert_id,
sd.id as select_id
from (select id, row_number() over (order by id) as rn from add_data) ad
inner join select_data sd on ad.rn = sd.rn;

Increment based on max value BigQuery

I have two tables.
TABLE A:
OBJECTID ID
NULL 41230
NULL 00004
NULL 00005
TABLE B:
OBJECTID ID
241231 00001
241230 00002
I'm trying to write a query that increments values for the OBJECTID field in Table A based on the max value in Table B. For example the OBJECTID field for the first row in Table A would then be 241232.
Using ROW_NUMBER() over (Order by OBJECTID ASC) works if I wanted to start with the value 1 and increment. But I need it to join on Table B and start on Table B's max value and then increment.
I've tried this but get a query error Query error: Table-valued function not found tableB:
UPDATE `tableA`
SET OBJECTID = (SELECT MAX(OBJECTID) as seq
FROM `tableB`
((SELECT ROW_NUMBER() over (Order by seq ASC))
)) WHERE OBJECTID IS NULL;
In BigQuery is easier create a new table that overwrite the actual. You can do it with this select:
with max_id as (
select max(objectid) as objectid from tableB
),
table_a_new_id as (
select
* except (objectid),
(select objectid from max_id) + dense_rank() over (order by id) as objectid
from tableA
where objectid is null
)
select * from table_a_new_id
union all
select * from tableA where objectid is not null
If you can't replace the table directly, you can save the result in a temporary table and then run the update:
update tableA
set tableA.objectid = new_table_a.objectid
from temp_new_tableA
where tableA.objectid is null and tableA.id = temp_new_tableA.id

Finding a random sample of unique data across multiple columns - SQL Server

Given a set of data in a SQL Server database with the following columns
AccountID, UserID_Salesperson, UserID_Servicer1, UserID_Servicer2
All three columns are primary keys from the same users table. I need to find a random sample that will include every UserID available in all three columns no matter the position while guaranteeing the fewest unique AccountID's possible.
--SET UP TEST DATA
CREATE TABLE MY_TABLE
(
AccountID int,
UserID_Salesperson int,
UserID_Servicer1 int,
UserID_Servicer2 int
)
INSERT INTO MY_TABLE (AccountID, UserID_Salesperson, UserID_Servicer1, UserID_Servicer2)
VALUES (12345, 1, 1, 2)
INSERT INTO MY_TABLE (AccountID, UserID_Salesperson, UserID_Servicer1, UserID_Servicer2)
VALUES (12346, 3, 2, 1)
INSERT INTO MY_TABLE (AccountID, UserID_Salesperson, UserID_Servicer1, UserID_Servicer2)
VALUES (12347, 4, 3, 1)
INSERT INTO MY_TABLE (AccountID, UserID_Salesperson, UserID_Servicer1, UserID_Servicer2)
VALUES (12348, 1, 2, 3)
--VIEW THE NEW TABLE
SELECT * FROM MY_TABLE
--NORMALIZE DATA (Unique List of UserID's)
SELECT DISTINCT MyDistinctUserIDList
FROM
(SELECT UserID_Salesperson as MyDistinctUserIDList, 'Sales' as Position
FROM MY_TABLE
UNION
SELECT UserID_Servicer1, 'Service1' as Position
FROM MY_TABLE
UNION
SELECT UserID_Servicer2, 'Service2' as Position
FROM MY_TABLE) MyDerivedTable
--NORMALIZED DATA
SELECT *
FROM
(SELECT AccountID, UserID_Salesperson as MyDistinctUserIDList, 'Sales' as Position
FROM MY_TABLE
UNION
SELECT AccountID, UserID_Servicer1, 'Service1' as Position
FROM MY_TABLE
UNION
SELECT AccountID, UserID_Servicer2, 'Service2' as Position
FROM MY_TABLE) MyDerivedTable
DROP TABLE MY_TABLE
For this example table, I could select AccountID (12347 and 12348) OR (12347 and 12346) to get the least accounts with all users.
My current solution is inefficient and can make mistakes. I currently select a random AccountID, insert the data into a temp table and try to find the next insert from something I have not already put in the temp table. I loop through the records until it finds something not used before… and after a few thousand loops it will give up and select any record.
I don't know how you guarantee the fewest account ids, but you can get one row per user id using:
select t.*
from (select t.*,
row_number() over (partition by UserId order by newid()) as seqnum
from my_table t cross apply
(values (t.UserID_Salesperson), (t.UserID_Servicer1), (t.UserID_Servicer2)
) v(UserID)
) t
where seqnum = 1;
Your original table doesn't have a primary key. Assuming that there is one row per account, you can dedup this so it doesn't have duplicate accounts:
select top (1) with ties t.*
from (select t.*,
row_number() over (partition by UserId order by newid()) as seqnum
from my_table t cross apply
(values (t.UserID_Salesperson), (t.UserID_Servicer1), (t.UserID_Servicer2)
) v(UserID)
) t
where seqnum = 1
order by row_number() over (partition by accountID order by accountID);

Send faulty rows to other table

I have a table with many columns in which I have to find the duplicate based on one column.
I.e. if I found duplicate customer_name in the Customer_name then
I have to remove all repeating from the source table.
Send all those rows to other table with same structure.
If you have two tables like this:
CREATE TABLE t1 (ID int, customerName varchar(64))
CREATE TABLE t2 (ID int, customerName varchar(64))
You can make something like this: (The ID column is for just to have a base for the deceision what to keep, you can change it as you need)
--First Copy
WITH CTE_T1
AS
(
SELECT
ID,
customerName,
ROW_NUMBER() OVER(PARTITION BY customerName ORDER BY ID) as OrderOfCustomer
FROM
t1
)
INSERT INTO t2
SELECT ID, customerName FROM cte_T1
WHERE OrderOfCustomer > 1;
--Then Delete
WITH CTE_T1
AS
(
SELECT
ID,
customerName,
ROW_NUMBER() OVER(PARTITION BY customerName ORDER BY ID) as OrderOfCustomer
FROM
t1
)
DELETE FROM CTE_T1
WHERE OrderOfCustomer > 1
Here is an SQLFiddle to show how it works.
I guess each row has a unique Id primary key.
This inserts into your duplicate rows table :
Insert into duplicateRowsTable
select * from myTable t1
where (select count(*) from myTable t2 where t1.customerId = t2.customerId) > 1
You delete from the duplicateRowsTable the good rows:
delete from duplicatesTable
where --this is not the faulty row for each customerId
finally you delete from your first table :
delete from myTable
where id IN (select id from duplicatesTable)
Try this:
For moving duplicates
INSERT Into DuplicatesTable
SELECT *
FROM
(SELECT *, ROW_NUMBER() OVER(PARTITION BY Customer_name ORDER BY Customer_name) As RowID,
FROM SourceTable) as temp
WHERE RowID > 1
For deteting:
WITH TableCTE
AS
(
SELECT *,
ROW_NUMBER() OVER(PARTITION BY Customer_name ORDER BY Customer_name) AS RowID
FROM SourceTable
)
DELETE
FROM TableCTE
WHERE RowID> 1