update multiple rows which is having null values - sql-server

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;

Related

what to use instead of union to join same results based on two where clauses

I have two queries that work as expected for example
Query 1
select Name,ID,Product,Question
from table 1
where Id= 9 and ProductID=30628
table output
Name | ID | Product | QUestion
0659e103-b33d-4603 |12356|Apple | is it picked up?
0659e103-b33d-4603 |12456|Apple |Available in store?
0659e103-b33d-4603 |12458|Apple |confirm order?
query 2
select Name,ID,Product,Question
from table 1
where Id= 9 and TypeID=2
table output
Name | ID | Product | QUestion
0659e103-b33d-4603 |12347|Apple | Problem at store?
as you can see in query 1 i use a ProductID and in query 2 i use a TypeID these two values gives me different out puts
so i used a union to join both as follows
select Name,ID,Product,Question
from table 1
where Id= 9 and ProductID=30628
union
select Name,ID,Product,Question
from table 1
where Id= 9 and TypeID=2
which i get the desired output
Name | ID | Product | QUestion
0659e103-b33d-4603 |12356|Apple | is it picked up?
0659e103-b33d-4603 |12456|Apple |Available in store?
0659e103-b33d-4603 |12458|Apple |confirm order?
0659e103-b33d-4603 |12347|Apple | Problem at store?
is their a better way to do this because my query will grow and i would not like to repeat the same thing over again. is their a better way to optimize the query?
NOte i can not use ProductID and TypeID on the same line because they do not result in accurate results
You could use OR since you are querying the same table.
SELECT Name
,ID
,Product
,Question
FROM TABLE1
WHERE (
Id = 9
AND ProductID = 30628
)
OR (
Id = 9
AND TypeID = 2
)
If you have a growing number of OR conditions you could use a temp table/variable and inner join to profit from a set based operation.
The inner join will only return matching rows.
CREATE TABLE #SomeTable(Id INT NOT NULL, ProductID INT NULL, TypeID INT NULL)
-- Insert all conditions you want to match.
INSERT INTO #SomeTable(Id, ProductID, TypeId)
VALUES (9, 30628, NULL)
, (9, NULL, 2)
SELECT Name
,ID
,Product
,Question
FROM TABLE1 x
INNER JOIN #SomeTable y ON
x.ID = y.ID -- Since ID is Not null in the temp table
AND (y.ProductID IS NULL OR y.ProductID = x.ProductID)
AND (y.TypeID IS NULL OR y.TypeID = x.TypeID)
You can use cas-when clause with a self join.
Case-when something like this:
SELECT t1_2.Name,
t1_2.ID,
t1_2.Product,
t1_2.Question,
(CASE WHEN (t1.Id= 9 and t1.ProductID=30628) THEN ID
WHEN (t1.Id= 9 and t1.TypeID=2) THEN ID
ELSE NULL) AS IDcalc
FROM table_1 t1 LEFT JOIN table_1 t1_2
ON t1.ID = t1_2.ID
WHERE (CASE WHEN (t1.Id= 9 and t1.ProductID=30628) THEN ID
WHEN (t1.Id= 9 and t1.TypeID=2) THEN ID
ELSE NULL) IS NOT NULL
You can use any table in the join.
In comparison of query performance the OR is much better until you have only one table, if you have more tables, then you should use temp table or case-when in your query.

T-SQL to find rows with at least one specific column value

Data set
Key Stage balance ForeignKey
---------------------------------------------
11805008 ABC 50 123
11805008 DEF 0 123
14567898 DEF 100 456
Query so far
Select key, two.Stage, two.balance
from table_a one, table_b two
where one.ForeignKey = two.foreignKey
I am looking for keys, stage and balance where key has stage of ABC and others. If key does not have stage ABC then it should not return any row for that key. But if that key has 'ABC' stage then it should return all rows for that key
Key Stage balance ForeignKey
11805008 ABC 50 123
11805008 DEF 0 123
You could use an IN clause to get all of the keys that have at least one stage of ABC. Also, use a more modern inner join syntax.
SELECT one.key, two.Stage, two.balance
FROM table_a one
INNER JOIN table_b two ON one.ForeignKey = two.foreignKey
WHERE key IN (
SELECT key
FROM table_a
INNER JOIN table_b ON table_a.ForeignKey = table_b.foreignKey
WHERE table_b.stage = 'ABC')
First, learn to use proper JOIN syntax.
Second, you can do this using window functions:
select key, stage, balance
from (Select key, two.Stage, two.balance,
sum(case when two.stage = 'ABC' then 1 else 0 end) over (partition by key) as num_abc
from table_a one join
table_b two
on one.ForeignKey = two.foreignKey
) t
where num_abc > 0;
Select key, two.Stage, two.balance
from table_a one
inner join table_b two
on one.foreignKey = two.foreignKey
where exists (
select 1 from table_b x
where x.foreignKey=one.foreignKey
and x.Stage='ABC' )
I can only assume what your original data is. The statement works on my demo, see here: http://rextester.com/SUTS17842

buLK Update duplicate row value

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.

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

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