解析备忘录中的数据 SQL
Parse data from a memo SQL
所以基本上我在数据库中有几个备忘录。我需要通过它们进行查询,并且只抓取备忘录中前面有日期的每个注释。所以如果我有这个例如:
abc def ghi jkl 9/1/17: mno pqr
我只想抓住 9/1/17: mno pqr
部分
有些甚至在第一个初始日期之后还有更多条目,如下所示:
abc def ghi jkl 9/1/17: mno pqr 9/2/17: stu vwx yz
在这种情况下,我需要 9/1/17: mno pqr
和 9/2/17: stu vwx yz
。
可能像这样将每个值放在一个新行中:
1: 9/1/17: mno pqr
2: 9/2/17: stu vwx yz
这样,如果顺序不对,我可以根据需要重新排序。
如有任何帮助,我们将不胜感激!谢谢
您可以使用 charindex 或 patindex
假设,
1. 除了日期之外,您的文本不会包含“/”
2. 您的日期将以 '/'
作为分隔符
下面的查询将 return 在您的字符串中第一次出现“/”。
SELECT PATINDEX('%/%', yourcolumn)
FROM yourtable
来自上述查询的值 return - 2 将是您日期的开始位置。整个字符串的长度 - 从上述查询中得到的值 return 将是输出的长度。
SELECT susbtring(yourcolumn, PATINDEX('%/%', yourcolumn) -2,
length(yourcolumn)-PATINDEX('%/%', yourcolumn))
FROM yourtable
如果您希望处理多个日期,那么您必须使用递归 CTE
您可以使用 PatternSplitCM(以下函数的 DDL)。解决方案如下所示(请注意,您需要 SQL Server 2012+ 到 运行 因为我使用的是 LEAD):
declare @string varchar(255) =
'abcdefg 9/21/17 took the notes. 9/23/17 printed the notes. 9/21/17 took the notes. 9/23/17 printed the notes.'
select ItemNumber = concat(ItemNumber/2,':'), Item
from
(
select ItemNumber, item = item +' '+ LEAD(item, 1) OVER (ORDER BY itemNumber), [Matched]
from dbo.PatternSplitCM(@string, '[0-9/]')
) ExtractDates
where [Matched] = 1;
结果
ItemNumber Item
------------ ----------------------------
1: 9/21/17 took the notes.
2: 9/23/17 printed the notes.
3: 9/21/17 took the notes.
4: 9/23/17 printed the notes.
函数
-- PatternSplitCM will split a string based on a pattern of the form
-- supported by LIKE and PATINDEX
--
-- Created by: Chris Morris 12-Oct-2012
ALTER FUNCTION [dbo].[PatternSplitCM]
(
@List VARCHAR(8000) = NULL
,@Pattern VARCHAR(50)
) RETURNS TABLE WITH SCHEMABINDING
AS
RETURN
WITH numbers AS (
SELECT TOP(ISNULL(DATALENGTH(@List), 0))
n = ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
FROM
(VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) d (n),
(VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) e (n),
(VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) f (n),
(VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) g (n))
SELECT
ItemNumber = ROW_NUMBER() OVER(ORDER BY MIN(n)),
Item = SUBSTRING(@List,MIN(n),1+MAX(n)-MIN(n)),
[Matched]
FROM (
SELECT n, y.[Matched], Grouper = n - ROW_NUMBER() OVER(ORDER BY y.[Matched],n)
FROM numbers
CROSS APPLY (
SELECT [Matched] = CASE WHEN SUBSTRING(@List,n,1) LIKE @Pattern THEN 1 ELSE 0 END
) y
) d
GROUP BY [Matched], Grouper;
所以基本上我在数据库中有几个备忘录。我需要通过它们进行查询,并且只抓取备忘录中前面有日期的每个注释。所以如果我有这个例如:
abc def ghi jkl 9/1/17: mno pqr
我只想抓住 9/1/17: mno pqr
部分
有些甚至在第一个初始日期之后还有更多条目,如下所示:
abc def ghi jkl 9/1/17: mno pqr 9/2/17: stu vwx yz
在这种情况下,我需要 9/1/17: mno pqr
和 9/2/17: stu vwx yz
。
可能像这样将每个值放在一个新行中:
1: 9/1/17: mno pqr
2: 9/2/17: stu vwx yz
这样,如果顺序不对,我可以根据需要重新排序。
如有任何帮助,我们将不胜感激!谢谢
您可以使用 charindex 或 patindex
假设, 1. 除了日期之外,您的文本不会包含“/” 2. 您的日期将以 '/'
作为分隔符下面的查询将 return 在您的字符串中第一次出现“/”。
SELECT PATINDEX('%/%', yourcolumn)
FROM yourtable
来自上述查询的值 return - 2 将是您日期的开始位置。整个字符串的长度 - 从上述查询中得到的值 return 将是输出的长度。
SELECT susbtring(yourcolumn, PATINDEX('%/%', yourcolumn) -2,
length(yourcolumn)-PATINDEX('%/%', yourcolumn))
FROM yourtable
如果您希望处理多个日期,那么您必须使用递归 CTE
您可以使用 PatternSplitCM(以下函数的 DDL)。解决方案如下所示(请注意,您需要 SQL Server 2012+ 到 运行 因为我使用的是 LEAD):
declare @string varchar(255) =
'abcdefg 9/21/17 took the notes. 9/23/17 printed the notes. 9/21/17 took the notes. 9/23/17 printed the notes.'
select ItemNumber = concat(ItemNumber/2,':'), Item
from
(
select ItemNumber, item = item +' '+ LEAD(item, 1) OVER (ORDER BY itemNumber), [Matched]
from dbo.PatternSplitCM(@string, '[0-9/]')
) ExtractDates
where [Matched] = 1;
结果
ItemNumber Item
------------ ----------------------------
1: 9/21/17 took the notes.
2: 9/23/17 printed the notes.
3: 9/21/17 took the notes.
4: 9/23/17 printed the notes.
函数
-- PatternSplitCM will split a string based on a pattern of the form
-- supported by LIKE and PATINDEX
--
-- Created by: Chris Morris 12-Oct-2012
ALTER FUNCTION [dbo].[PatternSplitCM]
(
@List VARCHAR(8000) = NULL
,@Pattern VARCHAR(50)
) RETURNS TABLE WITH SCHEMABINDING
AS
RETURN
WITH numbers AS (
SELECT TOP(ISNULL(DATALENGTH(@List), 0))
n = ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
FROM
(VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) d (n),
(VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) e (n),
(VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) f (n),
(VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) g (n))
SELECT
ItemNumber = ROW_NUMBER() OVER(ORDER BY MIN(n)),
Item = SUBSTRING(@List,MIN(n),1+MAX(n)-MIN(n)),
[Matched]
FROM (
SELECT n, y.[Matched], Grouper = n - ROW_NUMBER() OVER(ORDER BY y.[Matched],n)
FROM numbers
CROSS APPLY (
SELECT [Matched] = CASE WHEN SUBSTRING(@List,n,1) LIKE @Pattern THEN 1 ELSE 0 END
) y
) d
GROUP BY [Matched], Grouper;