I have a column called favorite_question
which is updated as following:
if it is null
then insert a value
if not null then old value + , + new value
if((select Favorite_question from User_Details where User_Id = @userid) IS NULL)
begin
update User_Details
set Favorite_question = (cast(@questionid as varchar(50)))
where User_Id = @userid
end
else
begin
update User_Details
set Favorite_question = ((select Favorite_question
from User_Details
where User_Id = @userid ) + ',' +
(cast(@questionid as varchar(50))))
where User_Id = @userid
end
where @userid
is users value and @questionid
is question value
favorite_question
is taken as varchar(50)
I want to remove a value from this column randomly
for eg.
if column values are = 2,6,8,9,5 and I want to remove 8 from it or any from the above
what would be the sql query for the same.
The UPDATE statement can be optimised a lot. The whole "if((select ..." can be replaced by:
UPDATE User_Details
SET Favorite_question = COALESCE(Favorite_question + ',', '') +
cast(@questionid as varchar(50))
where User_Id = @userid
Now on for your real question: how to remove text (a number) from the Favorite_questions column. Suppose the column holds the value '2,6,8,9,5'. If you want to remove the 2, you get ',6,8,9,5', so one has to add processing logic to remove the orphaned comma at the beginning. If you want to remove the 5, you get '2,6,8,9,', so one has to add processing logic to remove the orphaned comma at the end. If you want to remove the 8, you get '2,6,,9,5', so one has to add processing logic to remove one of the double comma's in the middle. What if the column holds the value '12,6,8,29,5,2' and you want to remove '2', you would not want to end up with something like: '1,6,8,9,5'.
Basically we should spend A LOT of effort to get removing a number from that text correct and leave the text in a clean state (no ',6,8,9,5', '2,6,,9,5' or the like). SQL is not that good at text processing.
The basic problem is that your data model is not normalised. You should remove the column Favorite_question from the User_Details table and create an extra table User_FavoriteQuestions (User_Id, Question_id) to store the FavoriteQuestions for your users. Your first UPDATE statement would then be replaced by
INSERT INTO User_FavoriteQuestions (User_Id, Question_id)
VALUES(@userid, @questionid)
Your real question becomes:
DELETE FROM User_FavoriteQuestions
WHERE User_Id = @userid AND Question_id = @questionid
Once you normalise your data model, manipulating it with SQL becomes a lot easier.
Ok, this level of string manipulation isn't really SQL's forte. However, it is possible...
Firstly, if you're going to do this on more than a single string (or even if that is the case) you may want to put this into a function.
To make it easier, one approach is to have a number table that contains just a list of consecutive numbers. This can be made as a permanent table but for this example I'm showing it as temporary.
declare @numberList table
(
NumberID int
)
It can be populated in a tedious fashion but a neat trick from http://blogs.lessthandot.com/index.php/DataMgmt/DataDesign/the-ten-most-asked-sql-server-questions--1#3
insert into @numberList
select number from master..spt_values
where type = 'P'
Next you want to separate out the original text into the individual parts:
declare @question varchar(20)
declare @questionTable table
(
qNo int identity(1,1),
qChar varchar(10)
)
set @question = '2,6,8,9,5'
set @question = ',' + @question + ','
insert into @questionTable(qChar)
select SUBSTRING(@question,NumberID + 1,CHARINDEX(',', @question, NumberID + 1) - NumberID - 1)
from @numberList
where NumberID <= LEN(@question)-1
and SUBSTRING(@question, NumberID, 1) = ','
Then you need to determine a random part to remove
declare @numberCount int
declare @seed int
declare @posn int
select @numberCount = count(*) from @questionTable
set @seed = (DATEPART(mm, getdate())) * 100000 +( DATEPART(ss, getdate()) * 1000) + datepart(ms, getdate())
set @posn = (RAND(@seed) * @numberCount) + 1
Then remove the part from the temporary table:
delete from @questionTable where qNo = @posn
Then get back the remaining parts:
declare @output varchar(20)
select @output = coalesce(@output+',', '') + qChar
from @questionTable
You can do this without going via temporary tables but there are a lot of CHARINDEXs and REPLACEs...
There are a couple of steps needed to pull the string manipulation of.
declare @S varchar(20)
declare @R varchar(20)
-- String of values
set @S = '2,6,8,9,5'
-- Value to remove
set @R = '8'
-- Add extra commas before and after
set @S = ','+@S+','
set @R = ','+@R+','
-- Remove the value
set @S = stuff(@S, charindex(@R, @S), len(@R)-1, '')
-- Remove extra commas
set @S = substring(@S, 2, len(@S)-2)
select @S
Result:
2,6,9,5
If you need to do this with and update you can use cross apply to handle the steps:
declare @T table
(
S varchar(20)
)
insert into @T values('2,6,8,9,5')
declare @R varchar(20)
set @R = '8'
update T1
set S = substring(T3.S, 2, len(T3.S)-2)
from @T as T1
cross apply (select ','+T1.S+',') as T2(S)
cross apply (select stuff(T2.S, charindex(','+@R+',', T2.S), len(@R)+1, '')) as T3(S)
select *
from @T
My best guess is that you can use Merge to Update / Insert using a single statement
-- Merge Statement
MERGE User_Details AS udp USING (SELECT Favorite_question, User_Id FROM User_Details
where User_Id = @userid ) AS uds
ON udp.User_Id = uds.User_Id
WHEN MATCHED THEN UPDATE SET udp.Favorite_question = udp.Favorite_question +',' + (cast(@questionid as varchar(50)))
WHEN NOT MATCHED THEN INSERT(User_Id ,Favorite_question ) VALUES(uds.User_Id ,(cast(@questionid as varchar(50))) );
GO
For same details see my blog:
http://tryconcepts.blogspot.in/2012/03/merge-to-update-insert-using-single.html
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.