我有一个名为Days
的列表。 Days
列存储以逗号分隔的字符串,表示星期几。例如,值1,2
代表Sunday, Monday
。我想将它转换为JSON并将其存储在同一个表中名为Frequency
的列中,而不是将此信息存储为逗号分隔的字符串。例如,应更新Days
值为1,2
的记录,以便将以下内容存储在Frequency
列中:
'{"weekly":"interval":1,"Sunday":true,"Monday":true,"Tuesday":false,"Wednesday":false,"Thursday":false,"Friday":false,"Saturday":false}}'
我找到了一种使用case语句的方法,假设Days
列中只有一个数字,如下所示:
UPDATE SCH_ITM
SET
FREQUENCY =
CASE
WHEN SCH_ITM.DAYS = 1 THEN '{"weekly":{"interval":1,"Sunday":true,"Monday":false,"Tuesday":false,"Wednesday":false,"Thursday":false,"Friday":false,"Saturday":false}}'
WHEN SCH_ITM.DAYS = 2 THEN '{"weekly":{"interval":1,"Sunday":false,"Monday":true,"Tuesday":false,"Wednesday":false,"Thursday":false,"Friday":false,"Saturday":false}}'
WHEN SCH_ITM.DAYS = 3 THEN '{"weekly":{"interval":1,"Sunday":false,"Monday":false,"Tuesday":true,"Wednesday":false,"Thursday":false,"Friday":false,"Saturday":false}}'
WHEN SCH_ITM.DAYS = 4 THEN '{"weekly":{"interval":1,"Sunday":false,"Monday":false,"Tuesday":false,"Wednesday":true,"Thursday":false,"Friday":false,"Saturday":false}}'
WHEN SCH_ITM.DAYS = 5 THEN '{"weekly":{"interval":1,"Sunday":false,"Monday":false,"Tuesday":false,"Wednesday":false,"Thursday":true,"Friday":false,"Saturday":false}}'
WHEN SCH_ITM.DAYS = 6 THEN '{"weekly":{"interval":1,"Sunday":false,"Monday":false,"Tuesday":false,"Wednesday":false,"Thursday":false,"Friday":true,"Saturday":false}}'
WHEN SCH_ITM.DAYS = 7 THEN '{"weekly":{"interval":1,"Sunday":false,"Monday":false,"Tuesday":false,"Wednesday":false,"Thursday":false,"Friday":false,"Saturday":true}}'
END
WHERE SCH_TYPE = 'W';
然而,我似乎无法找到一种有效的方法来处理将1,5
之类的值转换为正确的JSON表示。显然我可以写出所有可能的排列,但肯定是更好的方法吗?
答案 0 :(得分:1)
借助解析功能和交叉应用
;with cteDays As (Select ID,Name From (Values(1,'Sunday'),(2,'Monday'),(3,'Tuesday'),(4,'Wednesday'),(5,'Thursday'),(6,'Friday'),(7,'Saturday')) D(ID,Name))
Update YourTable Set Frequency = '{"weekly":"interval":1,'+String+'}}'
From YourTable A
Cross Apply (
Select String = Stuff((Select ','+String
From (
Select String='"'+Name+'":'+case when RetVal is null then 'false' else 'true' end
From [dbo].[udf-Str-Parse](A.Days,',') A
Right Join cteDays B on RetVal=ID) N
For XML Path ('')),1,1,'')
) B
Select * from YourTable
更新表
Days Frequency
1,2 {"weekly":"interval":1,"Sunday":true,"Monday":true,"Tuesday":false,"Wednesday":false,"Thursday":false,"Friday":false,"Saturday":false}}
1,2,3 {"weekly":"interval":1,"Sunday":true,"Monday":true,"Tuesday":true,"Wednesday":false,"Thursday":false,"Friday":false,"Saturday":false}}
UDF(如果需要)
CREATE FUNCTION [dbo].[udf-Str-Parse] (@String varchar(max),@Delimiter varchar(10))
Returns Table
As
Return (
Select RetSeq = Row_Number() over (Order By (Select null))
,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
From (Select x = Cast('<x>'+ Replace(@String,@Delimiter,'</x><x>')+'</x>' as xml).query('.')) as A
Cross Apply x.nodes('x') AS B(i)
);
--Select * from [dbo].[udf-Str-Parse]('Dog,Cat,House,Car',',')
--Select * from [dbo].[udf-Str-Parse]('John Cappelletti was here',' ')
答案 1 :(得分:1)
好的,这将为您提供您所要求的内容
create table test (days varchar(20), frequency varchar(500))
insert into test(days) values('1'),('2'),('3'),('4'),('5'),('6'),('7'),('1,5')
update test set frequency = '{"weekly":{"interval":1,'
+ '"Sunday": ' + case when days like '%1%' then 'true' else 'false' end + ','
+ '"Monday": ' + case when days like '%2%' then 'true' else 'false' end + ','
+ '"Tuesday": ' + case when days like '%3%' then 'true' else 'false' end + ','
+ '"Wednesday": ' + case when days like '%4%' then 'true' else 'false' end + ','
+ '"Thursday": ' + case when days like '%5%' then 'true' else 'false' end + ','
+ '"Friday": ' + case when days like '%6%' then 'true' else 'false' end + ','
+ '"Saturday": ' + case when days like '%7%' then 'true' else 'false' end + '}}'
select * from test
当然,例如Days ='1234'将产生与'1,2,3,4'相同的效果 - 就像'Bl4arg3le12'一样。如果Days是一个字符串,你可以把'8'放在没有意义的地方吗?
听起来你需要一两个额外的桌子,这是真的:
如果“MyTable”是带有Days列的表,请添加带有星期几的Days表,然后使用MyTableDays表将MyTable条目链接到天 - 对于1,5示例,将有两行MyTableDays