SQL Server Combine multiple text injection

mmvthczy  于 2023-10-15  发布在  其他
关注(0)|答案(2)|浏览(113)

I have a table that has these records on SQL Server

  1. RepID iBegin iEnd RepText
  2. 1 10 17 This is a profile of ... Moreover Toyota has been ... such as Mazda also ...
  3. 1 38 44 This is a profile of ... Moreover Toyota has been ... such as Mazda also ...
  4. 1 77 82 This is a profile of ... Moreover Toyota has been ... such as Mazda also ...
  5. 2 21 24 ... flights to USA will be...weather temp is 73 degrees ...
  6. 2 82 82 ... flights to USA will be...weather temp is 73 degrees ...

this table has a text (HTML) and I need to highlight the text that is in between iBegin and iEnd by adding the <red> before and after the highlighted text

I did that on the row level

  1. SELECT RepID, RepText, SUBSTRING(RepText,0, iBegin) + '<red>' + SUBSTRING(RepText,iBegin, iEnd-iBegin + 1) + '<\red>' + SUBSTRING(RepText, iEnd, Len(RepText)-iEnd + 1)
  2. FROM table

but could not do that with group by so all highlights show in a single record like this

  1. RepID RepText
  2. 1 This is a <red>profile</red> of ... Moreover <red>Toyota</red> has been ... such as <red>Mazda</red> also ...
  3. 2 ... flights to <red>USA</red> will be...weather temp is <red>73</red> degrees ...

Any idea how to do that?

yjghlzjz

yjghlzjz1#

Depending on your version of SQL Server and whether such string processing is best done in the database...

  1. with data as (
  2. select RepID, iBegin + 1 as iBegin, iEnd + 1 as iEnd, RepText, /* adjust to 1-based index */
  3. 1 + lag(iEnd, 1, 0) over (partition by RepID order by iBegin) as prevBegin,
  4. 1 + max(iEnd) over (partition by RepID) as lastBegin
  5. from T
  6. )
  7. select RepID,
  8. string_agg(
  9. concat(
  10. substring(RepText, prevBegin, iBegin - prevBegin),
  11. '<red>',
  12. substring(RepText, iBegin, iEnd - iBegin),
  13. '</red>'
  14. ), ''
  15. ) within group (order by iBegin)
  16. + substring(min(RepText), min(lastBegin), 1000)
  17. from data
  18. group by RepID;

This handles each wrapped segment with the non-wrapped segment just before it (via lag() ) in pairs. Each of those must then be concatenated in proper order along with the final segment at the end. This does assume no overlap in your offsets but that's pretty much a given anyway.

https://dbfiddle.uk/n2beW4E0

展开查看全部
f5emj3cl

f5emj3cl2#

I'm not sure if your iBegin and iEnd are correct... Here's a way to do it with a UDF and GROUP BY :

First the UDF

  1. CREATE OR ALTER FUNCTION dbo.Repl(@text nvarchar(max), @words nvarchar(max))
  2. RETURNS nvarchar(max)
  3. AS
  4. BEGIN
  5. DECLARE @pre nvarchar(max) = '';
  6. SET @words = @words + ';';
  7. WHILE LEN(@words) > 0
  8. BEGIN
  9. SET @pre = LEFT(@words, CHARINDEX(';', @words) - 1);
  10. SET @text = REPLACE(@text, @pre, ' <red>' + SUBSTRING(@pre, 2, LEN(@pre) - 1) + '<\red> ');
  11. SET @words = REPLACE(@words, @pre + ';', '');
  12. END
  13. RETURN @text
  14. END;

Then the call would be

  1. WITH pre AS
  2. (
  3. SELECT
  4. RepID,
  5. RepText,
  6. STRING_AGG(' ' + SUBSTRING(RepText, iBegin + 1, iEnd - iBegin) + ' ', ';') AS Words
  7. FROM [table]
  8. GROUP BY RepID, RepText
  9. )
  10. SELECT
  11. RepID,
  12. dbo.Repl(RepText, Words) AS RepText
  13. FROM pre;

And if your data looks like this, you would get your expected output:

  1. CREATE TABLE [table]
  2. (
  3. RepID int,
  4. iBegin int,
  5. iEnd int,
  6. RepText nvarchar(max)
  7. );
  8. INSERT INTO [table]
  9. VALUES
  10. (1, 10, 17, 'This is a profile of ... Moreover Toyota has been ... such as Mazda also ...'),
  11. (1, 34, 40, 'This is a profile of ... Moreover Toyota has been ... such as Mazda also ...'),
  12. (1, 62, 67, 'This is a profile of ... Moreover Toyota has been ... such as Mazda also ...'),
  13. (2, 15, 18, '... flights to USA will be...weather temp is 73 degrees ...'),
  14. (2, 45, 47, '... flights to USA will be...weather temp is 73 degrees ...');
展开查看全部

相关问题