MSSQL: How to remove duplicate column values from different tables? - sql-server

How to remove duplicate column values from different tables?
Given the following tables without foreign key reference:
Table A
Id IdentifierString
-------------------
1 String A
2 String B
3 String C
Table B
Id IdentifierString
-------------------
1 String A
2 String C
3 String D
I want to remove all duplicate column values:
Table A
Id IdentifierString
-------------------
1 NULL
2 String B
3 NULL
Table B
Id IdentifierString
-------------------
1 NULL
2 NULL
3 String D
How is this doable?

This could be done using UNION ALL, HAVING(COUNT ) and UPDATE statement as below:
CREATE TABLE Table1 (Id INT, IdentifierString VARCHAR (20));
INSERT INTO Table1 (Id, IdentifierString) VALUES
(1, 'String A'),
(2, 'String B'),
(3, 'String C');
CREATE TABLE Table2 (Id INT, IdentifierString VARCHAR (20));
INSERT INTO Table2 (Id, IdentifierString) VALUES
(1, 'String A'),
(2, 'String C'),
(3, 'String D');
DECLARE #DuplicateEntries TABLE (IdentifierString VARCHAR(20));
INSERT INTO #DuplicateEntries (IdentifierString)
SELECT IdentifierString FROM (
SELECT IdentifierString FROM Table1
UNION ALL
SELECT IdentifierString FROM Table2
) A
GROUP BY IdentifierString
HAVING COUNT(IdentifierString) > 1;
UPDATE T1
SET T1.IdentifierString = NULL
FROM Table1 T1
JOIN #DuplicateEntries D ON D.IdentifierString = T1.IdentifierString;
UPDATE T2
SET T2.IdentifierString = NULL
FROM Table2 T2
JOIN #DuplicateEntries D ON D.IdentifierString = T2.IdentifierString;
SELECT * FROM Table1;
SELECT * FROM Table2;
Please find the working demo on db<>fiddle

Here's your dml script to remove duplicates.
delete from table1 where id in (select id from (
select id, t1.IdentifierString, t2.IdentifierStringfrom table1 t1
left join table2 t2 on t2.IdentifierString= t1.IdentifierString) as t3
where isnull(t1.IdentifierString, '') = '' or isnull(t2.IdentifierString, '') = '')
delete from table2 where id in (select id from (
select id, t1.IdentifierString, t2.IdentifierStringfrom table2 t1
left join table1 t2 on t2.IdentifierString= t1.IdentifierString) as t3
where isnull(t1.IdentifierString, '') = '' or isnull(t2.IdentifierString, '') = '')

Related

Check duplicated value from temp table

I have a source table:
ID Value
1 a
2 b
3 c
4 d
And a temp table #ABCD:
ID Value
1 b
2 a
3 d
I want to update the original table from temp table based on Id match:
Original table:
ID Value
1 b
2 a
3 d (duplicate)
4 d
So now my original table has a duplicate value (d)
So how to get the duplicate value (d) from temp table #ABCD? Before updating.
Query:
CREATE TABLE [dbo].[Original](
[Id] [int] NOT NULL,
[Value] [nchar](10) NOT NULL
)
GO
INSERT INTO [dbo].[Original]
([Id]
,[Value])
VALUES
(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')
GO
CREATE TABLE #ABCD([Id] INT, [Value] nchar(10))
GO
INSERT INTO #ABCD([Id], [Value]) VALUES (1, 'b'), (2, 'a'), (3, 'd')
Result:
Duplicated value:
ID Value
3 d
EDIT
Maybe this is better:
select q2.* from (
select * from #ABCD
union
select * from original where id not in(select id from #ABCD)
)q1
inner join #ABCD q2
on q1.Value = q2.Value
and q1.id<>q2.id
Try this. I did the update in another temp table and evaluate the final result.
DROP TABLE IF EXISTS #TMP
select * into #TMP
from original
update t1
set t1.Value = t2.value
from #TMP t1
inner join #ABCD t2
on t1.id=t2.id
select a.* from #TMP t1
inner join #ABCD t2
on t1.Value=t2.Value
and t1.id<>t2.id

Count how many times a word exist in column

I have a table 1:
CREATE TABLE table1
INSERT INTO table1 values('XYZ')
INSERT INTO table1 values('ABC')
INSERT INTO table1 values('XYZ~ABC~AAA')
INSERT INTO table1 values('123')
Then, I have string 'ABC~XYZ~123'. I need to split this string into each word by using SQL:
Select VALUE FROM STRING_SPLIT('ABC~XYZ~123','~')
The return is table2
ABC
XYZ
123
I want to count how many times each word in table2 existed in table 1
The expected output is
ABC|3
XYZ|2
123|1
Any ideas on this?
If I understand your case correctly, the next statement may help:
Text and table:
DECLARE #text varchar(100) = 'ABC~XYZ~123'
CREATE TABLE Data (
Id int,
[Text] varchar(100)
)
INSERT INTO Data
(Id, [Text])
VALUES
(1, 'XYZ'),
(2, 'ABC'),
(3, 'XYZ~ABC~AAA'),
(4, '123~ABC')
Statement:
SELECT t.[value] AS [Word], j.[Count]
FROM STRING_SPLIT(#text, '~') t
LEFT JOIN (
SELECT s.[value], COUNT(*) AS [Count]
FROM Data d
CROSS APPLY STRING_SPLIT(d.[Text], '~') s
GROUP BY s.[value]
) j ON t.[value] = j.[value]
Result:
-----------
Word Count
-----------
ABC 3
XYZ 2
123 1
Apart from the suggestions as in comment you can use Count() function as below. But storing in this format will give you difficulty for the extraction as well as in join with the other tables.
Select T1Value, Count(*) as [NoCount] from(
Select table1.Value as T1Value, Value FROM STRING_SPLIT('ABC~XYZ~123','~')
inner join table1 on Value = table1.Value
)a group by T1Value
Edit
CREATE TABLE table1(
TableValue varchar(max)
);
INSERT INTO table1 (TableValue) values ( 'XYZ');
INSERT INTO table1 ( TableValue) values ( 'ABC');
INSERT INTO table1 ( TableValue) values ( 'XYZ~ABC~AAA');
INSERT INTO table1 ( TableValue) values ( '123~ABC');
SELECT b.value
,Count(*)
FROM (
SELECT VALUE
FROM STRING_SPLIT('ABC~XYZ~123', '~')
) a
INNER JOIN (
SELECT *
FROM table1
CROSS APPLY STRING_SPLIT(TableValue, '~')
) b ON a.Value = b.Value
GROUP BY b.Value
Here is the given Live Demo on db <> fiddle
Setup
create table STRINGS (ID int, STRINGS varchar(max));
insert into STRINGS (ID, STRINGS) values (1, 'XYZ');
insert into STRINGS (ID, STRINGS) values (1, 'ABC');
insert into STRINGS (ID, STRINGS) values (1, 'XYZ~ABC~AAA');
insert into STRINGS (ID, STRINGS) values (1, '123~ABC');
declare #VALUES varchar(max) = 'XYZ~ABC~123';
Calculation :
select V1.VALUE, count(STRINGS.ID)
from string_split(#VALUES,'~') V1
cross join STRINGS
outer apply string_split(STRINGS.STRINGS,'~') V2
where V2.VALUE = V1.VALUE
group by V1.VALUE
Result
-----------
Value Num
-----------
ABC 3
XYZ 2
123 1
Live exemple :
https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=15b95efcf69ea98fafbb7dda1c624551

SQL Server: How to select missing rows in table from another table?

I have two tables like below:
table1:
StoreId SKU
------------
1 abc
2 abc
3 abc
1 xyz
4 xyz
table2:
StoreId
--------
1
2
3
4
5
I want to select missing storeid from the table1 which are in table 2. But condition is that in above example for SKU abc storeid 4 and 5 are missing and for sku xyz 2,3,5 are missing. So I want below table as output
SKU,ID
------
abc 4
abc 5
xyz 2
xyz 3
xyz 5
I am able to pull only the overall missing store which is 5 using below query.
SELECT
SKU, t2.StoreId
FROM
#table1 t1
FULL OUTER JOIN
#table2 t2 ON t1.StoreId = t2.StoreId
WHERE
t1.StoreId IS NULL
Below is test create and insert query.
Declare #table1 As table
(
StoreId varchar(4),
SKU varchar(5)
)
Declare #table2 As table
(
StoreId int
)
BEGIN
Insert Into #table1(SKU,StoreId) values('abc',1)
Insert Into #table1(SKU,StoreId) values('abc',2)
Insert Into #table1(SKU,StoreId) values('abc',3)
Insert Into #table1(SKU,StoreId) values('xyz',1)
Insert Into #table1(SKU,StoreId) values('xyz',4)
Insert Into #table2(StoreId) values(1)
Insert Into #table2(StoreId) values(2)
Insert Into #table2(StoreId) values(3)
Insert Into #table2(StoreId) values(4)
Insert Into #table2(StoreId) values(5)
END
Thank you
You need to get a list of all skus and tables, and then show only rows which do not appear in table1:
select SKU, StoreID
from #table2 t2
cross join (select distinct sku from #table1) t1
where not exists (select 1 from #table1 table1
where table1.SKU = t1.SKU
and table1.StoreId = t2.StoreId)
Here is an alternative solution with the same result.
Syntax is very similar to the answer from #BeanFrog:
SELECT
t3.SKU, t2.StoreID
FROM
#table2 t2
CROSS JOIN
(SELECT distinct SKU
FROM #table1) t3
LEFT JOIN
#table1 t1
ON
t1.SKU = t3.SKU
and t1.StoreId = t2.StoreId
WHERE
t1.sku is null

How to insert records to one table to another table using SQL?

I Have two table name called Table1 & Table2.
Table1:
ID NAME AGE
-----------------
1 ABC 30
2 XYZ 40
3 XXX 50
4 aaa 60
Table2:
ID NAME AGE
-----------------
1 ABC 30
2 XYZ 40
3 XXX 50
I have to insert Table1 records to Table2. But I don't need to insert Existing item. I have to insert only unmatched data to Table2. How to do it.
E.g:
Table2 I am already have ID 1,2,3 but not 4. I have to insert only ID 4th rows.
Maybe
INSERT INTO Table2
SELECT * FROM Table1 WHERE ID NOT IN (SELECT ID FROM Table2)
Try this
insert into Table2
select * from Table1 t1
where not exists (select 1 from Table2 t2 where t2.ID=t1.ID)
You can achieve this by using LEFT JOIN too. Performance wise this is better than using IN operator.
INSERT INTO Table2 (ID, NAME, AGE)
SELECT T1.ID, T1.NAME, T1.AGE
FROM Table1 T1
LEFT JOIN Table2 T2 ON T2.ID = T1.ID
WHERE T2.ID IS NULL
Working execution with the given sample data:
DECLARE #Table1 TABLE (ID INT, NAME VARCHAR(50), AGE INT)
INSERT INTO #Table1 (ID, NAME, AGE)
VALUES
(1, 'ABC', 30),
(2, 'XYZ', 40),
(3, 'XXX', 50),
(4, 'aaa', 60)
DECLARE #Table2 TABLE (ID INT, NAME VARCHAR(50), AGE INT)
INSERT INTO #Table2 (ID, NAME, AGE)
VALUES
(1, 'ABC', 30),
(2, 'XYZ', 40),
(3, 'XXX', 50)
-- SELECT * FROM #Table2
INSERT INTO #Table2 (ID, NAME, AGE)
SELECT T1.ID, T1.NAME, T1.AGE
FROM #Table1 T1
LEFT JOIN #Table2 T2 ON T2.ID = T1.ID
WHERE T2.ID IS NULL
-- SELECT * FROM #Table2

How to make query to count values from two tables

I have three tables main 'maintable' table and two sub tables 'table1' and 'table2' the main table 'maintable' contains tow columns 'ID' and 'name' like that:
ID name
.... ......
1 Khalid
2 Jone
3 Steve
and the first sub table 'table1' contains 't1ID' and 'column' and 'ID' (foreign key) from 'maintable' like that:
t1ID column ID
...... ....... ....
1 Value 1
2 Value 1
3 Value 1
4 Value 2
and the second sub table 'table2' contains 't2ID' and 'column' and 'ID' (foreign key) from 'maintable' like that:
t2ID column ID
...... ....... ....
1 Value 2
2 Value 1
3 Value 1
4 Value 3
I want to make query to find count of (table1.ID) as A and count of (table2.ID) as B like that:
name A B
...... ... ...
khalid 3 2
Jone 1 1
Steve 0 1
Try this :
select name,
(select count(t1.ID) from table1 t1 where t1.ID = main.ID) as A,
(select count(t2.ID) from table2 t2 where t2.ID = main.ID) as B
from maintable main
Try this out:
;with cte1 as (
SELECT ID, COUNT(1) AS Cnt
FROM table1
GROUP BY ID
), cte2 as (
SELECT ID, COUNT(1) AS Cnt
FROM table2
GROUP BY ID
)
SELECT m.name, ISNULL(cte1.Cnt, 0) AS A, ISNULL(cte2.Cnt, 0) AS B
FROM maintable m
LEFT JOIN cte1 ON cte1.ID = m.ID
LEFT JOIN cte2 ON cte2.ID = m.ID
It can also be done with subqueries, but I like CTEs more (query is more readable).
Try this:
with t0_t1 as (
select
t.id,
t.nm,
count(t1.id) as A
from table0 t
left join table1 t1 on t.id = t1.id
group by t.id, t.nm
)
select t.nm, t.A, count(t2.id) as B
from t0_t1 t
left join table2 t2 on t.id = t2.id
group by t.nm, t.A
Example: http://sqlfiddle.com/#!6/341ff/10
create table table0 (id int, nm varchar(20));
insert into table0 values (1,'Khalid'),(2,'Jone'),(3,'Steve');
create table table1 (t1id int, col varchar(20), id int);
insert into table1 values
(1, 'v', 1), (2, 'v', 1), (3, 'v', 1), (4, 'v', 2);
create table table2 (t2id int, col varchar(20), id int);
insert into table2 values
(1, 'v', 2), (2, 'v', 1), (3, 'v', 1), (4, 'v', 3);
Result:
| nm | A | B |
|--------|---|---|
| Steve | 0 | 1 |
| Jone | 1 | 1 |
| Khalid | 3 | 2 |

Resources