buLK Update duplicate row value - sql-server

Update duplicate column value with
Suppose I have a table with follow column
ID, Code, IsDuplicate, Description
I have n records inside and I would like to bulk update the IsDuplicate value if there is duplicate code inside.
Example
1 ABC null null
2 DEF null null
3 DEF null null
4 ABC null null
5 FGH null null
ID 1, 2, 3, 4 IsDuplicate will be updated to true.
How could it be done?

This will update all duplicate codes :
UPDATE T
SET ISDUPLICATE = 'TRUE'
FROM YOURTABLE T
WHERE EXISTS (SELECT 1
FROM (SELECT *
FROM (SELECT ROW_NUMBER()
OVER (
PARTITION BY CODE
ORDER BY ID)RN,
*
FROM YOURTABLE)A
WHERE RN > 1)B
WHERE B.CODE = T.CODE)

You should use group by in select query.
SELECT code, COUNT(*) c FROM table GROUP BY code HAVING c > 1;
Then you can update it based on your requirements.

Related

update multiple rows which is having null values

I have table with two columns which id and name. Id contains null values and name contains some name value. There are duplicate rows in the table. The requirement is to update null values (id) with some value which is matching with name value. Find below table
Id Name
---------------
1 abc
1 abc
1 abc
1 abc
NULL abc
NULL abc
NULL abc
2 xyz
2 xyz
2 xyz
NULL xyz
NULL xyz
The above table which is having null values in the id column. I have to update Null values with Id. For example for abc I have to update 1 and for xyz have to update 2.
Use Self Join
update A
SET Id = B.id
FROM YourTable A
INNER JOIN YourTable B
ON a.Name = B.Name
WHERE A.id IS NULL
AND b.Id IS NOT NULL
Give it a go:
update MY_TABLE set id = new_id from
(
select id [new_id], name [new_name] from MY_TABLE
where id is not null
) A
where name = new_name
Let's assume the name of the table is 'names'.
Try executing the query below.
update names n set n.Id = (select max(Id) from names where upper(Name) = upper(n.Name)) where n.Id is null;

Exclude records for column A when B is null

Need help with a query that will let me exclude a record from column A if a record in column exist with a null.
Let's say i have two rows is column A named "test" they have column B values of 1 and null respectively. Here below is a query that I'm working on Object ID is column A and endversion is column B on my scenario.
select b.PortID,
max(endversion)as EndVersion,
d.ShortName as RuleName
from xr.ObjectPropertyValue a
join moxyportfolio b on a.objectid=b.portkey
join xr.AssignAllObjectsRule c on a.Objectclassid=c.ObjectClassID -- can replace with xr.assignobjectrule if it's rule is not assigned to all portfolios.
join xr.rulebase d on c.RuleID=d.RuleID
where objectid in (select objectid from xr.objectpropertyvalue where endversion is not null)
group by a.ObjectId, b.portid,d.ShortName
You can do this using HAVING:
select
b.PortID,
max(endversion) as EndVersion,
d.ShortName as RuleName
from xr.ObjectPropertyValue a
join moxyportfolio b
on a.objectid = b.portkey
join xr.AssignAllObjectsRule c
on a.Objectclassid = c.ObjectClassID -- can replace with xr.assignobjectrule if it's rule is not assigned to all portfolios.
join xr.rulebase d
on c.RuleID = d.RuleID
group by a.ObjectId, b.portid, d.ShortName
having sum(case when endversion is null then 1 else 0 end) = 0
Only select values for column A if column B is not null (and nothing otherwise):
SELECT COLA
FROM TABLE
WHERE COLB IS NOT NULL
Only select a value for column A if column B is not null (and null otherwise):
SELECT CASE WHEN COLB IS NOT NULL THEN COLA ELSE NULL END AS COLA
FROM TABLE

Use NOT Equal condition in sql?

I want to fetch orders that have a “Received” (ActivityID = 1) activity but not a “Delivered” (ActivityID = 4) activity on orders table. i.e orders that are received but not deliverd yet.
my query is
SELECT OrderID FROM tblOrderActivity
where (tblOrderActivity.ActivityID = 1 AND tblOrderActivity.ActivityID != 4)
GROUP BY OrderID
it is not returning desired result.
result should be orderID 2 and 4
Your query doesn't really make sense. Grouping happens after WHERE clause, so you're basically getting all orders that have ActivityID ==1 (because if activity Id is 1 there it's always not equal to 4).
After WHERE clause is applied you end up with following rows:
OrderID ActivityID
1 1
2 1
3 1
4 1
And these are the orders you group. No more condition is evaluated.
If 4 is the highest possible ActivityID you could do following:
SELECT OrderID
FROM tblOrderActivity
GROUP BY OrderID
HAVING MAX(ActivityID) < 4
HAVING condition is applied after grouping, which is what you want.
I don't think Group by is needed here. You can use a Subquery to find he order's which is not delivered. Try this.
SELECT *
FROM Yourtable a
WHERE a.ActivityID = 1
AND NOT EXISTS (SELECT 1
FROM yourtable b
WHERE a.OrderID = b.OrderID
AND b.ActivityID = 4)

if value is null get previous value sql server 2008

I have table that looks like this
Id Description
5 Null
4 This is a description
3 This is a description
2 Null
1 Null
I need to create an update statement that will update the null value if the previous value is not null.
Id Description
5 This is a description
4 This is a description
3 This is a description
2 Null
1 Null
Any advice or assistance would be much appreciated.
I think this is what you're looking for:
update toupdate
set description = updateto.description
from yourtable toupdate
join yourtable updateto on updateto.id = toupdate.id - 1
where updateto.description is not null
and toupdate.description is null;
SQL Fiddle Demo
This produces the following results:
ID DESCRIPTION
5 This is a description
4 This is a description
3 This is a description
2 (null)
1 (null)
EDIT: As pointed out by comment by Aaron Bertrand.
If your IDs aren't consecutive, you can use the row_number() function to join on instead of the ids:
with cte as (
select *, row_number() over (order by (select null)) rn
from yourtable
)
update toupdate
set description = updateto.description
from cte toupdate
join cte updateto on toupdate.rn = updateto.rn - 1
where updateto.description is not null
and toupdate.description is null;
You can change your order by criteria as needed.
Updated SQL Fiddle
The most common way (that I am aware of) to do this sort of thing is with a self-join:
-- WARNING: Untested Code
UPDATE YourTable
SET Origin.Description = Proxy.Description
FROM YourTable Origin
JOIN YourTable Proxy
ON Origin.Id = Proxy.Id - 1
WHERE Origin.Description IS NULL
AND Proxy.Description IS NOT NULL
This will join YourTable to itself so that one row looks like this:
Origin.Id | Origin.Description | Proxy.Id | Proxy.Description
------------------------------------------------------------------
5 | NULL | 4 | This is a description
EDIT
If you are not guaranteed always incrementing IDs then you will want to use ROW_NUMBER:
;WITH NumberedRows
AS
(
SELECT *
, ROW_NUMBER() OVER(ORDER BY Id) AS [Row #]
FROM YourTable
)
SELECT *
FROM NumberedRows Origin
JOIN NumberedRows Proxy
ON Origin.Id = Proxy.Id - 1
WHERE Origin.Description IS NULL
AND Proxy.Description IS NOT NULL

Query to collect data from previous rows

I have a table with records as, in example data below a CO.Nr are TH-123,Th-456 and so on... I need to collect the data..
Nr. CO.Nr Employee Resp Description Date
1 TH-123 ABC NULL HELLO 10.05.2010
2 TH-123 NULL S14 NULL 18.05.2010
3 TH-123 DEF NULL 13.05.2010
4 TH-456 XYZ NULL NULL 1.07.2010
5 TH-456 NULL S19 SOME NULL
6 TH-456 TEXT 08.05.2010
7 TH-456 NULL 28.05.2010
For TH-123,
If Nr. is maximum, that is the record i need to start with group by CO.Nr, so it is the record with Nr as 3,
if the value in the other columns is NULL or space, go to a record above that is the record with Nr as 2, even if it has null value go to a record above that record with Nr. as 1 in this case.
In the 3 records i need to take the maximum of date.
For the above data, i need to have output as,
CO.Nr Employee Resp Description Date
TH-123 DEF S14 HELLO 18.05.2010
TH-456 XYZ S19 TEXT 01.07.2010
Thanks in advance!
You can do it many ways
select [co.nr],
(select top(1) employee from mytable b where b.[co.nr]=a.[co.nr] and
employee is not null order by nr desc) as employee,
(select top(1) resp from mytable b where b.[co.nr]=a.[co.nr] and
resp is not null order by nr desc) as resp,
(select top(1) description from mytable b where b.[co.nr]=a.[co.nr] and
description is not null order by nr desc) as description,
(select max([date]) from mytable b where b.[co.nr]=a.[co.nr]) as Date
from (
select distinct [co.nr]
from mytable ) as a
You can use a subselect to choose the record you want, then join on that. Something like the following for the employees one (I'll leave the rest of the columns as an exercise):
SELECT MyTable.[CO.Nr], Employees.Employee
FROM MyTable
LEFT OUTER JOIN (SELECT FIRST(Employee) as Employee, [CO.Nr]
FROM MyTable
WHERE Employee IS NOT NULL AND Employee <> ''
GROUP BY [CO.Nr]
ORDER BY [Nr.] DESC) Employees
ON MyTable.[CO.Nr] = Employees.[CO.Nr]
GROUP BY MyTable.[CO.Nr]
Or, if FIRST() is not a valid aggregate function, as mentioned in your comments, you can try subselects in your SELECT clause, like:
SELECT t.MyTable.[CO.Nr],
(SELECT TOP(1) x.Employee
FROM MyTable x
WHERE x.[CO.Nr] = t.[CO.Nr]
AND x.Employee IS NOT NULL AND x.Employee <> ''
ORDER BY [Nr.] DESC) as Employee
FROM MyTable t
GROUP BY t.[CO.Nr]

Resources