SQL server : Replace the value using like operator - sql

I need to replace the column value if exists to another column have a same text as like below example.
create table #t1
(
a varchar(100)
)
create table #t2
(
b varchar(100),
c varchar(100)
)
insert into #t1 values('she is a girl teacher and he is a boy doctor')
insert into #t2 values('girl','G')
insert into #t2 values('boy','B')
select *from #t1
select *from #t2
select a=replace (t1.a,t2.b,t2.c)
from #t1 t1 inner join #t2 t2 on t1.a like '%'+t2.b+'%'
while i'm selecting the query the result displays like
she is a G teacher and he is a boy doctor
she is a girl teacher and he is a B doctor
but i have need the output like
she is a G teacher and he is a B doctor
How need to change my query for the above output.

The only solution I can think if using recursive queries.
create table #t1
(
a varchar(100)
)
create table #t2
(
b varchar(100),
c varchar(100)
)
insert into #t1 values('she is a girl teacher and he is a boy doctor')
, ('she is a girl soldier and he is a boy doctor')
, ('she is a girl dentist and he is a boy farmer')
insert into #t2 values('girl','G')
insert into #t2 values('boy','B')
select *from #t1
select *from #t2
select a=replace(t1.a,t2.b,t2.c), *
from #t1 t1
inner join #t2 t2 on t1.a like '%'+t2.b+'%';
with cte as (
select a, 1 as ct from #t1
union all
select cast(replace(a,t2.b,t2.c) as varchar(100)) as a, ct+1 from cte
cross apply #t2 t2 where a like '%'+t2.b+'%'
)select distinct a from (select a, ct as ct from cte) as t1 where t1.ct = (select max(ct) from cte);
drop table #t1
drop table #t2
-- she is a G teacher and he is a B doctor

The most straightforward way is to just use a cursor to loop through all the replacements, applying them.
create table #t1
(
a varchar(100)
)
create table #t2
(
b varchar(100),
c varchar(100)
)
insert into #t1 values('she is a girl teacher and he is a boy doctor')
insert into #t2 values('girl','G')
insert into #t2 values('boy','B')
-- We create a couple of variables and a temporal table to hold the incremental replacements
declare #Pattern varchar(64)
declare #Value varchar(64)
select * into #TempReplacements from #1
-- Apply the replacements
declare Replacements cursor for select b, c from #t2
open Replacements
fetch next from Replacements into #Pattern, #Value
while ##fetch_status = 0
update #TempReplacements set a = replace(a, #Pattern, #Value)
fetch next from Replacements into #Pattern, #Value
end
close Replacements
deallocate Replacements
-- We return the results
select * from #TempRelacements
-- Drop temporary Table
drop table #TempReplacements
drop table #t1
drop table #t2

Related

Delete from memory table if in another in memory table

I have 2 in memory tables #Holding and #P1
if the row is in #P1 I want to remove it from #Holding
With my code below the duplicates are not being removed. I do not have a primary Id key like many examples, For a unique row I have Drawing, Method and Location.
DELETE h
FROM #Holding h
INNER JOIN #P1 p1 ON p1.DRAWING = h.DRAWING and p1.Method = h.Method and
p1.LOCATION = h.LOCATION
You could try using a where exists
DELETE h
FROM #Holding h
WHERE EXISTS (
SELECT *
FROM #P1 p1
WHERE p1.DRAWING = h.DRAWING and p1.Method = h.Method and p1.LOCATION = h.LOCATION
)
if your duplicates are not being removed, is because the requirement to join with #P1 to find them is incorrect.
Just to show an example that the delete/join works as expected:
declare #t1 table (c1 int)
declare #t2 table (c1 int)
insert into #t1 values (1),(2),(3)
insert into #t2 values (1)
delete #t1
from #t1 t1
join #t2 t2
on t1.c1=t2.c1
select * from #t1

Insert to table based on another table if doesn’t exist

From doing a bit of research it seems it’s not possible to do an insert with a where clause?
I have a table I want to import into another table where specific record criteria doesn’t already exist. How would I go about this ?
E.g pseudo code -
insert into table b (select * from table a) where not exists tableb.column1 = tablea.column1 and tableb.column2 = tablea.column2
Could this potentially be done with a Join ?
You can insert using INSERT INTO.. SELECT with NOT EXISTS.
Query
insert into [TableB]
select * from [TableA] as [t1] -- [TableA] and [TableB] structure should be same.
where not exists(
select 1 from [TableB] as [t2]
where [t1].[column1] = [t2].[column1]
and [t1].[column2] = [t2].[column2]
);
Or, if the table structure is not same and need to same few columns, then
Query
insert into [TableB]([column1], [column2], ..., [columnN])
select [column1], [column2], ..., [columnN]
from [TableA] as [t1]
where not exists(
select 1 from [TableB] as [t2]
where [t1].[column1] = [t2].[column1]
and [t1].[column2] = [t2].[column2]
);
You can also use LEFT JOIN with IS NULL as below:
INSERT INTO tableb
SELECT a.*
FROM tablea a
LEFT JOIN tableb b ON b.column1 = a.column1
AND b.column2 = a.column2
WHERE b.column1 IS NULL
Referencing table name from INSERT statement in SELECT part will not work, because INSERT is not a query itself, but nothing prevents to query destination table in SELECT, which produces the data set to be inserted.
INSERT INTO tableb (column1, column2)
SELECT column1, column2 FROM tablea
WHERE NOT EXISTS (SELECT * FROM tableb
WHERE tableb.column1 = tablea.column1
AND tabled.column2 = tablea.column2)
Try this :
Via Insert with Select statement with Not Exists
Declare #table1 table(Id int , EmpName varchar(100) )
Declare #table2 table(Id int , EmpName varchar(100) )
Insert into #table1 values (1,'Ajay'), (2, 'Tarak') , (3,'Nirav')
Insert into #table2 values (1,'Ajay')
--Insert into table b (select * from table a) where not exists tableb.column1 = tablea.column1 and tabled.column2 = tablea.column2
INSERT INTO #table2 (id, empname)
select id, empname from #table1
EXCEPT
SELECT id, empname from #table2
Select * from #table1
Select * from #table2
Via merge
Insert into #table2 values (4,'Prakash')
Select * from #table1
Select * from #table2
Declare #Id int , #EmpName varchar(100)
;with data as (select #id as id, #empname as empname from #table1)
merge #table2 t
using data s
on s.id = t.id
and s.empname = t.empname
when not matched by target
then insert (id, empname) values (s.id, s.empname);
Select * from #table1
Select * from #table2

SQL Server hierarchy referencing and cross data referencing

This might be a stupid question, but I am not a DBA and kind of stuck with this issue. I have an application that trickles down all effects (asdf) under an applied ID (IDParent).
The data tables are setup like this:
Data Tables
3rd Data Table
I want to write a query that when using IDChild it will reference that entry's IDParent to get the parent ID while referencing it as an IDChild. For example for the data entry starting at 116 I want to use the parent ID (124) and get 321 in T1. I want to use this to get the RandoName associated with RandoID for all of the entries that has a parent ID of 321.
Right now I am using a script something like:
Select t.[NAME]
From T2 tv
Inner join T3 t on t.RandoID = tv.RandoId
Where
tv.IDChild = T1.IDChild OR tv.IDChild = T1.IDParent
but I'm not sure how to get the whole applied hierarchy.
This would yield something like this:
Resulting Query
PS. I can not change the tables/db schema. But maybe I can add one to do all the referencing? Please tell me what you think.
EDIT I'm sorry I forgot about this other stupid table that RandoID uses which contains the name of the RandoID. I am trying to get the name of RandoID
I think a loop could help you.
Try this:
CREATE TABLE #t1 (IDChild Int, IDParent Int);
CREATE TABLE #t2 (RandoID NVARCHAR(10) , IDChild Int);
CREATE TABLE #RandoName (RandoID NVARCHAR(10), RandoName VARCHAR(50));
INSERT INTO #t1 VALUES (321, NULL), (123,321),(124,123),(116,124)
INSERT INTO #t2 VALUES ('asdf', 123)
INSERT INTO #RandoName VALUES ('asdf', 'something')
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 100)) [RowNum], a.IDChild a, a.IDParent b, b.IDChild c INTO #t3 FROM #t1 a
LEFT OUTER JOIN #t1 b ON b.IDParent = a.IDChild
DECLARE #rownum INT;
DECLARE cbcursor CURSOR for Select RowNum FROM #t3;
OPEN cbcursor;
Fetch Next from cbcursor into #rownum
WHILE ##FETCH_STATUS = 0
BEGIN
UPDATE #t3
SET c = (SELECT b from #t3 where RowNum = #rownum-1)
WHERE RowNum = #rownum
Fetch Next from cbcursor into #rownum;
END;
Close cbcursor;
Deallocate cbcursor;
SELECT a,b,t2.RandoID, r.RandoName FROM #t3
LEFT OUTER JOIN #t2 t2 on t2.IDChild = #t3.c OR t2.IDChild = #t3.b OR t2.IDChild = #t3.a
LEFT OUTER JOIN #RandoName r on t2.RandoID = r.RandoID
This is what I get:
If you have any changes in your tables, like more records for T2, this script should be modified.
Using recursion:
declare #t table (IDc int , Idp int)
insert into #t
values
(321,null)
,(123,321)
,(124,123)
,(116,124)
declare #t2 table (RandoID varchar(10), IDChild int)
insert into #t2
values('asdf',123)
;with cte as
(
select anchor = IDChild
,ParentOrSelf = IDc
,RandoID
,RandomName
from #t
cross join (select RandoID,RandoName from #t2 t2 join #t3 t3 on t2.RandoID=t3.RandoID) crossed
where IDc=#anchor
union all
select t2.IDChild
,IDc
, t2.RandoID,RandomName
from #t t
cross join (select RandoID,RandoName from #t2 t2 join #t3 t3 on t2.RandoID=t3.RandoID) t2
join cte on cte.ParentOrSelf = t.Idp
)
select IDc
, cte.RandoID,cte.RandomName
from #t t
left join cte on t.IDc = cte.ParentOrSelf
Results:
IDc RandoID
321 NULL
123 asdf
124 asdf
116 asdf

Join Result Sets Mechanism

Look at a simple sql code:
declare #t1 table (id int);
insert into #t1(id) values(1),(2),(3);
select * from #t1
declare #t2 table (id int);
insert into #t2(id) values(9);
select * from #t2
select * from #t1, #t2; -- q1
select ds1.id from #t1 as ds1, (select id from #t2) as ds2 -- q2
Why result of q1 and q2 is different, aren't they supposed to be same?
declare #t1 table (id int);
insert into #t1(id) values(1),(2),(3);
select * from #t1
declare #t2 table (id int);
insert into #t2(id) values(9);
select * from #t2
select * from #t1, #t2; -- q1
select ds1.id from #t1 as ds1, (select id from #t2) as ds2
In this scenario, (select id from #t2) as ds2 is considered as a derived table. You didn't fetch the column in your query.
Try this:
select ds1.id,ds2.id
from #t1 as ds1,
(select id from #t2) as ds2 -- q2
OutPut:
id id
1 9
2 9
3 9

SQL select -one to many joins want to have the manys

I have two tables, TBL_PARENT (parentID, ParentName) and TBL_CHILDREN (ParentID,Child_Name)
A Parent can have 0 to many children
What I want is a query to give me a list of parent and their children in single row per parent.
For example
Parent1 John,Mary
Parent2 jane,steve,jana
And the number of rows to be the total number of parents
try this query :
I have created 3 table 2 of them are already created on your database #parant, #ch
and the third one is a temp table to put the result in.
create table #parant (id int , name varchar(10))
create table #ch (id int , name varchar(10), pid int)
insert into #parant select 1,'PA'
insert into #parant select 2,'PB'
insert into #parant select 3,'PC'
insert into #ch select 1,'Ca',1
insert into #ch select 1,'Cb',1
insert into #ch select 1,'Cc',1
insert into #ch select 1,'Cd',3
insert into #ch select 1,'Cf',3
insert into #ch select 1,'Ch',1
create table #testTable (id int, name varchar(10),chid int, chname varchar(10), cpid int)
insert into #testTable
select x.id , x.name ,isnull( y.id ,0), isnull(y.name,'') ,isnull(y.pid ,0)
from #parant as x
left outer join #ch as y
on x .id = y .pid
SELECT t.ID, t.name , STUFF(
(SELECT ',' + s.chname
FROM #TestTable s
WHERE s.ID = t.ID
FOR XML PATH('')),1,1,'') AS CSV
FROM #TestTable AS t
GROUP BY t.ID, t.name
GO
drop table #testTable
drop table #ch
drop table #parant
for the above data i got the following result
1 PA Ca,Cb,Cc,Ch
2 PB
3 PC Cd,Cf
SELECT COUNT(P.parentID),
P.ParentName,
C.Child_Name
FROM TBL_PARENT as P
INNER JOIN TBL_CHILDREN as C
WHERE P.parentID == c.ParentID
GROUP BY P.ParentName;
The line P.parentID == c.ParentID is doing the Join, and the line count(P.parentID) is doing the count of all the parents and the line GROUP BY P.ParentName is grouping all the rows by the name of the parent so you can display all the children of every single parent.