是否可以简化此 patindex 代码?

问题描述

我一直在寻找一种方法来简化下面的 patindex 代码,但尚未成功。有谁能告诉我这在 sql Server 中是否可行。

patindex('%'+'('+'[0-9][0-9]'+'/'+'[0-9][0-9]'+'/'+'[0-9][0-9][0-9][0-9]'+' - '+'[0-9][0-9]'+'/'+'[0-9][0-9]'+'/'+'[0-9][0-9][0-9][0-9]'+')'+'%',ii.description)

字符串总是包含日期部分,如 (17/09/2015 - 16/09/2016),我想从该字符串中获取两个日期。这个想法是我用两个日期寻找这个文本块的起点,然后用子字符串函数(和一些数学)计算开始和结束日期的位置和内容

如果有更简单或更好的方法来做到这一点,我愿意接受建议。非常感谢。

解决方法

有几种方法可以清理您所拥有的东西,也有很多方法可以解决这个问题。

DECLARE @text VARCHAR(100) = '(17/09/2015 - 16/09/2016)';

--==== Solution #1: Basic position matching
SELECT 
  Date1 = SUBSTRING(@text,2,10),Date2 = SUBSTRING(@text,15,10);

--==== Solution #2: Cleanup using APPLY
SELECT TheDate = PATINDEX('%('+fmt.Phone+' - '+fmt.Phone+')%',@text)
FROM   (VALUES('[0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]')) AS fmt(Phone);

--==== Solution #3: Use 2nd APPLY call for the Second Date; MUCH CLEANER!
SELECT
  Date1 = SUBSTRING(@text,p1.Pos,p1.Pos+12,10)
FROM        (VALUES('%[0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]%')) AS fmt(Phone)
CROSS APPLY (VALUES(PATINDEX(fmt.Phone,@text)))                      AS p1(Pos)
CROSS APPLY (VALUES(SUBSTRING(@text,10)))                  AS st2(Txt)

这三个查询返回:

Date1      Date2
---------- ----------
17/09/2015 16/09/2016

TheDate (location of first date)
-----------
1

Date1      Date2
---------- ----------
17/09/2015  16/09/201

使用 NGrams8k 时,这样的操作非常简单快捷。

--==== Solution #3 Ngrams8k
SELECT      TheDate = f.Dt
FROM        dbo.ngrams8k(@text,10)                   AS ng
CROSS APPLY (VALUES(TRY_CONVERT(DATE,ng.token,103))) AS f(Dt)
WHERE       CHARINDEX('/',ng.token) = 3
  AND       f.Dt IS NOT NULL;

--==== Solution #4 Ngrams8k with Pivot
SELECT
  Date1 = MAX(CASE f.RN WHEN 1 THEN f.DT END),Date2 = MAX(CASE f.RN WHEN 2 THEN f.DT END)
FROM
(
  SELECT      ROW_NUMBER() OVER (ORDER BY (SELECT NULL)),f.Dt
  FROM        dbo.ngrams8k(@text,10)                   AS ng
  CROSS APPLY (VALUES(TRY_CONVERT(DATE,103))) AS f(Dt)
  WHERE       CHARINDEX('/',ng.token) = 3
    AND       f.Dt IS NOT NULL
)  AS f(RN,DT); 

这些返回:

TheDate
----------
2015-09-17
2016-09-16

Date1      Date2
---------- ----------
2015-09-17 2016-09-16

第一个解决方案以行的形式返回日期,第二个解决方案是旋转的。无论您需要什么。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...