Show Duplicate Items/id in different column - sql

I've made a query to check duplicate items and to display duplicate id's in different columns rather than different rows.
SELECT uid, COUNT(*), Max(id) AS dupes1, MIN(id) AS dupes2
FROM table
GROUP BY uid
HAVING (COUNT(*) > 1)
Another Set of query
SELECT y.uid, x.id
FROM table x
JOIN (SELECT t.uid
FROM table t
GROUP BY t.uid
HAVING COUNT(t.uid) > 1) y ON y.uid = x.uid
where Len(y.uid) > 11
order by y.uid
This works fine for 2 duplicate item's but I want to show all the duplicate items in different columns
Expected Output
uid count dupes1 dupes2 dupes3 and so on...

SELECT uid, COUNT(*),
-- A varchar column to show all duplicates with the format 1,2,3
STUFF((
SELECT ',' + CAST(id AS varchar(10)) FROM table b WHERE a.uid = b.uid FOR XML PATH ('')
), 1, 1, '') AS dupes
FROM table a
GROUP BY uid
HAVING (COUNT(*) > 1)

Related

Select rows where one column has duplicate values based on another column which contains specific strings

I have a table where in customer number column contains duplicate values and I would like to select all rows where there are duplicate entries for customer number, but only select those rows where WO Type column only contains these specific values ('IMU','Electric') so in the table image attached to this question: I should only get rows for ID 1 and 2.
I do not want those duplicates counted where the pair of duplicate rows also contain GAS, but only want those duplicate rows which exclusively contain only IMU and Electric values in WO Type Column
Your help is much appreciated.
You can use group by and having:
select customerNumber
from t
where woType in ('EMU', 'Electric')
group by customerNumber
having count(*) = 2;
Note: This assumes no duplicates. To handle this, you can use:
having min(woType) <> max(woType)
or:
having count(distinct woType) = 2 -- number of elements in IN list
SELECT *
FROM tbl t1
WHERE EXISTS
(
SELECT * FROM tbl t2
WHERE t2.customernumber = t1.customernumber
AND t2.wotype = 'IMU'
) AND EXISTS
(
SELECT * FROM tbl t2
WHERE t2.customernumber = t1.customernumber
AND t2.wotype = 'Electric'
) AND NOT EXISTS
(
SELECT * FROM tbl t2
WHERE t2.customernumber = t1.customernumber
AND t2.wotype NOT IN ('IMU', 'Electric')
)
Here's a fiddle.
Try this:
select * from Table1 Main
Inner JOIN (
select Customer_Number
From Table1
group by Customer_Number
Having COunt(Customer_Number)>1) SUB ON Main.Customer_Number=SUB.Customer_Number
WHERE Main.Wo_Type IN ('IMU','Electric')
This Query will return the duplicate set or rows in the table.

select N-1 records for update

I have a query where I want to update n-1 records from result set. Can this be done without loops?
If my query is like this:
with cte(id, count)
as
(
select e.id, count(*) as count
from data
where id in (multiple values)
group by id
having count(*) >1
)
Now I want to update the rows in another table with the resulting id's but only any n-1 rows for each id value from the above query. Something like this:
update top( count-1 or n-1) from data2
inner join cte on data2.id = cte.id
set somecolumn = 'some value'
where id in (select id from cte)
The id column is not unique. There are multiple rows with the same id values in table data 2.
This query will do what you want. It uses two CTEs; the first generates the list of eligible id values to update, and the second generates row numbers for id values in data2 which match those in the first CTE. The second CTE is then updated if the row number is greater than 1 (so only n-1 rows get updated):
with cte(id, count) as (
select id, count(*) as count
from data
where id in (2, 3, 4, 6, 7)
group by id
having count(*) >1
),
cte2 as (
select d.id, d.somecolumn,
row_number() over (partition by d.id order by rand()) as rn
from data2 d
join cte on cte.id = d.id
)
update cte2
set somecolumn = 'some value'
where rn > 1
Note I've chosen to order row numbers randomly, you might have some other scheme for deciding which n-1 values you want to update (e.g. ordered by id, or ...).
Is this what you're looking for? The CTE identifies ALL of the source rows, but the WHEREclause in the UPDATE statement limits the updates to n-1.
WITH cte AS
(
SELECT
id,
ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS RowNum
FROM data
)
UPDATE t
SET t.<whatever> = <whateverElse>
FROM
otherTable AS t
JOIN
cte AS c
ON t.id = c.id
WHERE
c.RowNum > 1;
I believe this would work just fine
;with cte(id, count)
as
(
select e.id, count(*) as count
from data
where id in (multiple values)
group by id
having count(*) >1
)
update data
set soemcolumn = 'some value'
from data join cte on cte.id = data.id
;

comparing two tables and removing ones that match

I have two tables. MembID is the only column returned for each. The MembID can be in both tables but I would like to remove the ones that are in both from the results.
I'd like the final return to be 456 and 789 from Table A.
I've tried:
select distinct a.membid
from a
left join b on a.membid = b.membid
and b.num <> 1
it does not return any results.
Thanks.
try like below
select distinct a.membid
from a
left join b on a.membid = b.membid
where b.membid is null
The MembID can be in both tables but I would like to remove the ones that are in both from the results.
If you want members in only one table, here is one method:
select memberid
from ((select memberid, 1 as in_a, 0 as in_b from a
) union all
(select memberid, 0, 1 from b
)
) ab
group by memberid
having max(in_a) + max(in_b) = 0;
Note that this version allows duplicates within each table.
In databases that support set-based operators, you can also do:
(select memberid from a union
select memberid from b
) except -- sometimes this is minus
(select memberid from a intersect
select memberid from b
);
EDIT:
Your description of the problem doesn't match your data. You seem to want the members in a that are not in b. One method elaborates on the first:
select memberid
from ((select memberid, 1 as in_a, 0 as in_b from a
) union all
(select memberid, 0, 1 from b
)
) ab
group by memberid
having max(in_a) + max(in_b) = 0;
Or the second:
select memberid from a
except -- or minus
select memberid from b
However, I would typically do:
select distinct memberid
from a
where not exists (select 1 from b where b.memberid = a.memberid);

How to update value if one of the field has multiple same values in SQL

In my database table, one of the fields has the same values. I want to change this value with random number or string which is appended to this field value for uniqueness.
Sample Data
Here 'Ma' has 5 records and so on. I want to change Name Ma01, Ma02 etc.
Id Name Count
1 Ma 5
2 Ga 6
3 Gu 5
How can do with SQL query
Try this
UPDATE TBL
SET Name = A.Name
FROM
(
SELECT
Id,
Name + CAST(ROW_NUMBER() OVER (PARTITION BY Name ORDER BY (SELECT NULL)) AS NVARCHAR(500)) AS NAME,
Count
FROM
TBL
WHERE
NAME IN
(
SELECT T.NAME FROM TBL T
GROUP BY T.NAME
HAVING COUNT(1) > 1
)
) A
WHERE
TBL.Id = A.ID
Try this:
Select Name + convert(varchar(2), row_number()over(partition by Name order by Name))
From tablename
You just try this.
Declare #i int = 1
update yourtable
set ID = #i , #i = #i + 1
Select Code based on NEER`s code with leading zero added, tested on MSSQL database.
SELECT
Id,
Name,
Name + RIGHT('00'+CAST(ROW_NUMBER() OVER (PARTITION BY Name ORDER BY (SELECT Name)) AS NVARCHAR(MAX)),2) AS Updatedname
FROM
tablename
WHERE
Name IN
(
SELECT T.NameFROM tablename T
GROUP BY T.Name
HAVING COUNT(Name) > 1
)
GROUP BY Name,Id
ORDER BY Name

How to Order BY without having Column in SELECT

I am using MS-SQL and I have a table like this:
Count Code
1 A
2 C
3 A
4 B
5 C
6 B
I need to only to get Distinct Row of the Code Column but I need to keep the Order of the Column to create a Comma Delimited String like this:
A, C, B
I have tried the following code to not get an SQL Error of Msg 145, Level 15 - ORDER BY items must appear in the select list if SELECT DISTINCT is specified.
SELECT #tlist = ISNULL(#tlist+', ','') + Code
FROM (SELECT DISTINCT t.Code
FROM #Table t)
but I get an output of A, B, C
So, you don't want distinct. You want group by:
select t.code
from #Table t
group by t.code
order by min(count)
You can order by columns not mentioned in the select clause.
To get the comma delimited list as a single variable, use this technique:
select stuff((select ', '+t.code
from #Table t
group by t.code
order by min(count)
for xml path ('')
), 1, 2, '')
Order by in a subquery is generally undefined. And, your method of concatenating the list together in order is not guaranteed to work.
order them in your subquery
SELECT DISTINCT t.Code
FROM #Table t
ORDER BY t.Code