Update a column based on column in the same table - sql-server

I am trying to write an update statement that will update the newTableNo column based on the other columns in the same table.
This is what I have.
childNo | parentNo |TableID |newTableNo
--------+----------+--------+---------+
26 | NULL | 750 | NULL |
27 | NULL | 751 | NULL |
28 | 27 | 752 | NULL |
29 | 27 | 753 | NULL |
30 | 27 | 754 | NULL |
34 | NULL | 800 | NULL |
This is expected.
childNo | parentNo |TableID |newTableNo
--------+----------+--------+---------+
26 | NULL | 750 | NULL |
27 | NULL | 751 | NULL |
28 | 27 | 752 | 751 |
29 | 27 | 753 | 751 |
30 | 27 | 754 | 751 |
34 | NULL | 800 | NULL |
If parentNo is NULL then newTableNo is defintely NULL
If parentNo is not null then it has related childNo(s)
Format table

declare #table table (childNo int, parentNo int, TableID int, NewTableNo int)
insert into #table
values
(26,NULL,750,NULL),
(27,NULL,751,NULL),
(28,27,752,NULL),
(29,27,753,NULL),
(30,27,754,NULL),
(34,NULL,800,NULL)
update t2
set t2.newTableNo = t.TableID
from #table t
full join #table t2 on t2.parentNo = t.childNo
select * from #table
You could also do this with an inner join
update t
set t.newTableNo = t2.TableID
from #table t
INNER JOIN #table t2 ON t.parentNo = t2.childNo
where t.parentNo is not null
select * from #table

It looks like you want to use:
UPDATE t1
SET newTableNo = parents.TableID
FROM
t1
INNER JOIN
(SELECT * FROM t1 WHERE parentNo IS null) parents
ON
Parents.childno = t1.parentNo

You can try this script to update newTableNo column
declare #table table (childNo int, parentNo int, TableID int, NewTableNo int)
insert into #table
values
(26,NULL,750,NULL),
(27,NULL,751,NULL),
(28,27,752,NULL),
(29,27,753,NULL),
(30,27,754,NULL),
(34,NULL,800,NULL)
UPDATE t
SET t.newTableNo = tt.TableID
FROM #table t
INNER JOIN #table tt ON t.parentNo = tt.childNo
WHERE t.parentNo IS NOT NULL
select * from #table

To update :
UPDATE mytable SET newTableNo = t2.TableID FROM mytable
LEFT JOIN (SELECT childNo,TableID FROM mytable) t2 ON t2.childNo = parentNo
Not that if parentNo or TableID updates, newTableNo may turn obsolete.
You can select that value easily without create an actual data column:
SELECT t1.childNo, t1.parentNo, t1.TableID, t2.TableID AS newTableNo
FROM mytable t1
LEFT JOIN mytable t2 ON t2.childNo = t1.parentNo

Related

Extract numbers from string in sql

In my Table there is a column called Comment and it contains data like
input
Comment
| 22 | 22 | INTERNAL AUDIT | NM | OK
| Multiplied by 4 | 32 | 32 | INTERNAL AUDIT | TR | None
| 19 | 17 | INTERNAL AUDIT | LM | FIXED
| REF#R7F282CT
we need to extract only numbers from this comment column and update into other column
need output like this like:
col1 col2
22 22
32 32
19 17
null null
input image
Output image
Using Split Function
declare #temp1 table (Comment varchar(255))
insert into #temp1 values ('| 22 | 22 | INTERNAL AUDIT | NM | OK')
insert into #temp1 values ('| Multiplied by 4 | 32 | 32 | INTERNAL AUDIT | TR | None')
insert into #temp1 values ('| 19 | 17 | INTERNAL AUDIT | LM | FIXED')
insert into #temp1 values ('| REF#R7F282CT')
declare #temp2 table (Comment varchar(255),numeric_values varchar(100))
insert into #temp2
Select Comment,[value] as numeric_values
from #temp1
CROSS APPLY string_split(Comment,'|')
WHERE ISNUMERIC([value]) = 1
--select * from #temp2
SELECT Comment,
MAX(CASE WHEN Row_Num = 1 THEN numeric_values END) Col1,
MAX(CASE WHEN Row_Num = 2 THEN numeric_values END) Col2
FROM (
SELECT Comment,numeric_values,
ROW_NUMBER() OVER(PARTITION BY comment ORDER BY (select null)) as Row_Num
FROM #temp2
) d
GROUP BY Comment

tuning resultset without temp table

Table1 (orgumcae)
caseid | auth_status_summary | delegate_system
-------+---------------------+----------------
100 | 1 | 14
200 | 2 | 13
SQL:
create table orgumcae(caseid int, auth_status_summary int, delegate_system int);
insert into orgumcae values(100, 1, 14);
insert into orgumcae values(200, 2, 13);
Table2 (stringlocale)
id | subid | string
----+-------+--------
148 | 1 | AAA
148 | 2 | BBB
148 | 3 | CCC
148 | 14 | DDD
152 | 11 | WWW
152 | 12 | XXX
152 | 13 | YYY
152 | 14 | ZZZ
SQL:
create table stringlocale(id int, subid int, string varchar(40));
insert into stringlocale values(148,1,'AAA');
insert into stringlocale values(148,2,'BBB');
insert into stringlocale values(148,14,'DDD');
insert into stringlocale values(152,11,'WWW');
insert into stringlocale values(152,13,'YYY');
insert into stringlocale values(152,14,'ZZZ');
Resultset
caseid | auth_status_summary |auth_status_summary_string | delegate_system | delegate_system_string
-------+---------------------+---------------------------+-----------------+-----------------------
100 | 1 | AAA | 14 | ZZZ
200 | 2 | BBB | 13 | YYY
There are 2 tables Table1 and Table2 and a Resultset. Can I get some help to achieve the Resultset without using temp tables?
Here auth_status_summary column of Table1 denotes 148 value for column id of Table2 and delegate_system column of Table1 denotes 152 value for column id of Table2, so for auth_status_summary use where clause table2.id = 148 for delegate_system use where clause table2.id = 152
Select case_id, t1.auth_status_summary, t2.string, t1.delegate_system, t22.string
from table1 as t1
inner join table2 as t2 on t1.auth_status_summary = t2.subid
inner join table2 as t22 on t1.delegate_system = t22.subid
This should do:
select t1.caseid,
t1.auth_status_summary,
t2_auth.string as auth_status_summary_string,
t1.delegate_system,
t2_deleg.string as delegate_system_string
from orgumcae t1
left outer join stringlocale t2_auth
on t2_auth.id = 148
and t2_auth.subid = t1.auth_status_summary
left outer join stringlocale t2_deleg
on t2_deleg.id = 152
and t2_deleg.subid = t1.delegate_system
order by 1
The key part is to use the Table2 (stringlocale) twice, with different aliases.
See this db<>fiddle

how to copy TreeView's rows from the same table and update with different ID column and copy the parent_id

I want copy the table and put different value on column Type= B and auto_increment id and copy the parent id
Table = Menu
Id | parent_id | order | section | name | url | type
100 | NULL | 7 | web | Tasks | ~/en/Tasks | A
102 | 100 | 1 | web | Pages | ~/en/Pages | A
103 | 100 | 4 | web | Category | ~/en/Category | A
104 | NULL | 3 | web | DLM | ~/en/DLM | A
105 | 104 | 6 | web | ONS | ~/en/ONS | A
106 | 104 | 2 | web | HBO | ~/en/HBO | A
107 | NULL | 7 | web | Tasks | ~/en/Tasks | B
108 | 107 | 1 | web | Pages | ~/en/Pages | B
109 | 107 | 4 | web | Category | ~/en/Category | B
110 | NULL | 3 | web | DLM | ~/en/DLM | B
111 | 110 | 6 | web | ONS | ~/en/ONS | B
112 | 110 | 2 | web | HBO | ~/en/HBO | B
This probably isn't the most efficient, but it gets the job done. It assumes that name is unique. I left out columns unnecessary to the example. Also, you can't put a variable into the identity clause, so that needs to be wrapped in an EXEC
IF OBJECT_ID (N'paths', N'U') IS NOT NULL
DROP TABLE paths
IF OBJECT_ID (N'new_paths', N'U') IS NOT NULL
DROP TABLE new_paths
CREATE TABLE paths (
id INT,
parent_id INT,
name NVARCHAR(20)
)
INSERT INTO dbo.paths
(id,parent_id,name)
VALUES
(100, NULL, 'Tasks'),
(102, 100, 'Pages'),
(103, 100, 'Category'),
(104, NULL, 'DLM'),
(105, 104, 'ONS'),
(106, 104, 'HBO')
DECLARE #start_value INT
SET #start_value = (SELECT MAX(id) FROM paths) + 1
DECLARE #sql nvarchar(1000)
SET #sql = N'
CREATE TABLE new_paths (
id INT IDENTITY(' + CAST(#start_value AS nvarchar) + ',1),
parent_id INT,
name NVARCHAR(20)
)
'
EXEC sp_executesql #stmt = #sql
INSERT INTO new_paths (parent_id,name)
SELECT Parent_id, name FROM dbo.paths
;WITH mappings AS (
SELECT n.*, p.id AS old_id
FROM new_paths n
INNER JOIN paths p
ON p.name = n.name
)
UPDATE n
SET n.parent_id = m.id
FROM new_paths n
INNER JOIN mappings m
ON m.old_id = n.parent_id
--SELECT * FROM new_paths
Please see below approach to resolve an issue, ask questions in the comments if something is unclear, I have added some explanation in code comments
EDITED, to manage GUID (as per comment)
-- declare table var
declare #table table ([Increment] int identity(1,1), Id uniqueidentifier, [parent_id] nvarchar(50), [order] int, [section] nvarchar(50), [name] nvarchar(50), [url] nvarchar(50), [type] nvarchar(50))
-- insert values into this table
insert into #table
select [Id],
[parent_id],
[order],
[section],
[name],
[url],
'B'
from your_table
where [type] = 'A'
-- loop your temp table
declare #max_temp int = (select max(Increment) from #table)
declare #curr int = 1
declare #parent_value uniqueidentifier = null
while (#curr <= #max_temp)
begin
-- do diffrent inserts depend on parent_id value
if (select parent_id from #table) = null
begin
-- set below var, it will be used in next insert where parent_id is not null
set #parent_value = (select Id from #table where Increment = #curr)
insert into your_table ([parent_id], [order], [section], [name], [url], [type])
select
[parent_id],
[order],
[section],
[name],
[url],
[type]
from #table
where Id = #curr
end
else
begin
insert into your_table ([parent_id], [order], [section], [name], [url], [type])
select
isnull(#parent_value, [parent_id]),
[order],
[section],
[name],
[url],
[type]
from #table
where Id = #curr
end
-- update current
set #curr = #curr + 1
end

Update All other Records Based on a single record

I have a table with a million records. I need to update some columns which are null based on the existing 'not null' records of a particular id based columns. I've tried with one query, it seems to be working fine but I don't have confidence in it that it will be able to update all those 1 million records exactly the way I need. I'm providing you some sample data how my table looks like.Any help will be appreciated
SELECT * INTO #TEST FROM (
SELECT 1 AS EMP_ID,10 AS DEPT_ID,15 AS ITEM_NBR ,NULL AS AMOUNT,NULL AS ITEM_NME
UNION ALL
SELECT 1,20,16,500,'ABCD'
UNION ALL
SELECT 1,30,17,NULL,NULL
UNION ALL
SELECT 2,10,15,1000,'XYZ'
UNION ALL
SELECT 2,30,16,NULL,NULL
UNION ALL
SELECT 2,40,17,NULL,NULL
) AS A
Sample data:
+--------+---------+----------+--------+----------+
| EMP_ID | DEPT_ID | ITEM_NBR | AMOUNT | ITEM_NME |
+--------+---------+----------+--------+----------+
| 1 | 10 | 15 | NULL | NULL |
| 1 | 20 | 16 | 500 | ABCD |
| 1 | 30 | 17 | NULL | NULL |
| 2 | 10 | 15 | 1000 | XYZ |
| 2 | 30 | 16 | NULL | NULL |
| 2 | 40 | 17 | NULL | NULL |
+--------+---------+----------+--------+----------+
Expected result:
+--------+---------+----------+--------+----------+
| EMP_ID | DEPT_ID | ITEM_NBR | AMOUNT | ITEM_NME |
+--------+---------+----------+--------+----------+
| 1 | 10 | 15 | 500 | ABCD |
| 1 | 20 | 16 | 500 | ABCD |
| 1 | 30 | 17 | 500 | ABCD |
| 2 | 10 | 15 | 1000 | XYZ |
| 2 | 30 | 16 | 1000 | XYZ |
| 2 | 40 | 17 | 1000 | XYZ |
+--------+---------+----------+--------+----------+
I tried this but I'm unable to conclude whether it is updating all the 1 million records properly.
SELECT * FROM #TEST T
inner JOIN #TEST T1 ON T1.EMP_ID=T.EMP_ID
WHERE T1.AMOUNT IS NOT NULL
UPDATE T SET AMOUNT=T1.AMOUNT
FROM #TEST T
inner JOIN #TEST T1 ON T1.EMP_ID=T.EMP_ID
WHERE T1.AMOUNT IS not NULL
I have used UPDATE using inner join
UPDATE T
SET T.AMOUNT = X.AMT,T.ITEM_NME=X.I_N
FROM #TEST T
JOIN
(SELECT EMP_ID,MAX(AMOUNT) AS AMT,MAX(ITEM_NME) AS I_N
FROM #TEST
GROUP BY EMP_ID) X ON X.EMP_ID = T.EMP_ID
SELECT * into #Test1
FROM #TEST
WHERE AMOUNT IS NOT NULL
For records validation run this query first
SELECT T.AMOUNT, T1.AMOUNT, T1.EMP_ID,T1.EMP_ID
FROM #TEST T
inner JOIN #TEST1 T1 ON T1.EMP_ID=T.EMP_ID
WHERE T.AMOUNT IS NULL
Begin Trans
UPDATE T
SET T.AMOUNT=T1.AMOUNT, T.ITEM_NME= = T1.ITEM_NME
FROM #TEST T
inner JOIN #TEST1 T1 ON T1.EMP_ID=T.EMP_ID
WHERE T.AMOUNT IS NULL
rollback
SELECT EMP_ID,MAX(AMOUNT) as AMOUNT MAX(ITEM_NAME) as ITEM_NAME
INTO #t
FROM #TEST
GROUP BY EMP_ID
UPDATE t SET t.AMOUNT = t1.AMOUNT, t.ITEM_NAME = t1.ITEM_NAME
FROM #TEST t INNER JOIN #t t1
ON t.emp_id = t1.emp_id
WHERE t.AMOUNT IS NULL and t.ITEM_NAME IS NULL
Use MAX aggregate function to get amount and item name for each employee and then replace null values of amount and item name with those values. For validation use COUNT function to calculate the number of rows with values of amount and item name as null. If the number of rows is zero then table is updated correctly

Split table in two tables plus a link table

I have a table with three columns with double values, but no double rows. Now I want to split this table in two table with unique values and a link table. I think the Problem gets clearer when I Show you example tables:
Original:
| ID | Column_1 | Column_2 | Column_3 |
|----|----------|----------|----------|
| 1 | A | 123 | A1 |
| 2 | A | 123 | A2 |
| 3 | B | 234 | A2 |
| 4 | C | 456 | A1 |
Table_1
| ID | Column_1 | Column_2 |
|----|----------|----------|
| 1 | A | 123 |
| 2 | B | 234 |
| 3 | C | 456 |
Table_2
| ID | Column_3 |
|----|----------|
| 1 | A1 |
| 2 | A2 |
Link-Table
| ID | fk1 | fk2 |
|----|-----|-----|
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 2 | 2 |
| 4 | 3 | 1 |
Table_1 I created like this:
INSERT INTO Table_1(Column_1, Column_2)
SELECT DISTINCT Column_1, Column_2 FROM Original
WHERE Original.Column_1 NOT IN (SELECT Column_1 FROM Table_1)
Table_2 I created in the same way.
The question now is, how to create the Link-Table?
The original table does grow continuesly, so only new entries should be added.
Do I have to use a Cursor, or is there a better way?
SOLUTION:
MERGE Link_Table AS LT
USING (SELECT DISTINCT T1.ID AS T1ID, T2.ID AS T2ID FROM Original AS O
INNER JOIN Table_1 AS T1 ON T1.Column_1 = O.Column_1
INNER JOIN Table_2 AS T2 ON T2.Column_3 = O.Column_3) AS U
ON LT.fk1 = U.T1ID
WHEN NOT MATCHED THEN
INSERT (fk1, fk2)
VALUES (U.T1ID, U.T2ID);
You can JOIN all 3 tables to get proper data for link table:
--INSERT INTO [Link-Table]
SELECT t1.ID,
t2.ID
FROM Original o
INNER JOIN Table_1 t1
ON t1.Column_1 = o.Column_1
INNER JOIN Table_2 t2
ON t2.Column_3 = o.Column_3
If your original table will grow, then you need to use MERGE to update/insert new data.
You have to inner join your Original,Table_1 and Table_2 to get the desired result.
Try like this, Its similar to gofr1 post.
DECLARE #orginal TABLE (
ID INT
,Column_1 VARCHAR(10)
,Column_2 INT
,Column_3 VARCHAR(10)
)
DECLARE #Table_1 TABLE (
ID INT
,Column_1 VARCHAR(10)
,Column_2 INT
)
DECLARE #Table_2 TABLE (
ID INT
,Column_3 VARCHAR(10)
)
Insert into #orginal values
(1,'A',123,'A1')
,(2,'A',123,'A2')
,(3,'B',234,'A2')
,(4,'C',456,'A1')
Insert into #Table_1 values
(1,'A',123)
,(2,'B',234)
,(3,'C',456)
Insert into #Table_2 values
(1,'A1')
,(2,'A2')
SELECT O.ID
,T1.ID
,T2.ID
FROM #orginal O
INNER JOIN #Table_1 T1 ON T1.Column_1 = O.Column_1
INNER JOIN #Table_2 T2 ON T2.Column_3 = O.Column_3

Resources