从sql select * EDITED *的where子句中的substring获取日期

时间:2011-12-22 18:58:45

标签: sql sql-server sql-server-2008 select substring

我在一个文本字段中存储了一个日期和其他文本。为什么他们不把它放在日期字段中?我不知道,但我现在没有权力改变它。在代码的其他地方,我这样做是为了获取此日期在某个范围内的记录。它工作正常。

For Each i As InventoryItem In inventoryList
  index = i.Notes.IndexOf("on {") + 4
  scanned_dt = i.Notes.Substring(index, i.Notes.Length - index - 1)
  If Date.Parse(scanned_dt) >= startDate And Date.Parse(scanned_dt) <= endDate Then
    ...

我现在正在尝试获取特定日期范围的项目总数。 此sql语句用于获取所有日期的总计。如何更新Where子句以仅计算i.Notes包含startDateendDate之间的日期的项目

Dim sql As String = "Select COUNT(inv_PartNum) from lester.inventory i join lester.vendor v on v.vendor_ID = i.vendor_ID Where v.vendor_Name = '" + vendorName + "' AND i.inv_Desc LIKE '%" + size + "%'"

*的 EDITED * 我想出了这个sql select语句:

SELECT COUNT(i.inv_PartNum) FROM cdms.lester.inventory AS I
join CDMS.lester.vendor AS v on v.vendor_ID = i.vendor_ID Where v.vendor_Name = 'JVE-285' 
AND CONVERT(DATETIME,
SUBSTRING(i.inv_Notes, CharIndex('on {', i.inv_Notes)+4, len(i.inv_Notes)-(CharIndex('on {', i.inv_Notes) + 4)
),101) BETWEEN '01-01-2011' AND '04-04-2011'

但我收到此错误: 将char数据类型转换为日期时间数据类型会导致日期时间值超出范围。

在尝试解决这个问题时,我创建了以下sql select语句:

SELECT * FROM (
SELECT i.inv_Notes, 
CONVERT(DATETIME,SUBSTRING(i.inv_Notes, CharIndex('on {',i.inv_Notes)+4,LEN(i.inv_Notes)-(CharIndex('on {', i.inv_Notes) + 4)),101) AS d
FROM cdms.lester.inventory AS i
join CDMS.lester.vendor AS v ON v.vendor_ID = i.vendor_ID WHERE v.vendor_Name = 'JVE-285') AS s

我的inv_Notes列包含一个字符串,如{4/8/2011}上的“分配给工具预告片{JVE-285}”

当我运行如上所示的查询时,我得到了inv_Notes列和日期列。所有日期均以“2011-04-08 00:00:00.000”格式显示,并且不会出现任何错误。

但是,只要我添加一个WHERE子句,就会收到错误:将char数据类型转换为datetime数据类型导致了一个超出范围的datetime值。

我尝试过每个方向格式化日期,但总是得到错误......

WHERE s.d > CONVERT(DATETIME, '2011-1-1', 101)

WHERE s.d < GetDate()

WHERE s.d > '20110101'

WHERE s.d >= '2011-01-01'

WHERE s.d >= '01-01-2011'

WHERE s.d > '01/01/2011'

修改 我也试过了 WHERE s.d IS NOT NULL 并得到相同的错误。这显然不是我认为它在WHERE点工作b / c的方式,转换应该已经成功发生。

有这个工作

SELECT * FROM (
SELECT i.inv_Notes,
SUBSTRING(i.inv_Notes, CharIndex('} on {',i.inv_Notes)+6,LEN(i.inv_Notes)-(CharIndex('} on {', i.inv_Notes) + 6))
AS d
FROM cdms.lester.inventory AS i
join CDMS.lester.vendor AS v ON v.vendor_ID = i.vendor_ID WHERE v.vendor_Name = 'JVE-285') AS s
WHERE PARSENAME(REPLACE(s.d, '/', '.'), 1)+
RIGHT('00'+PARSENAME(REPLACE(s.d, '/', '.'), 3),2)+
RIGHT('00'+PARSENAME(REPLACE(s.d, '/', '.'),2),2) BETWEEN '20110407' AND '20110409'

我尝试将其转换为int并进行整数比较,但后来出现错误。弄清楚问题是某些inv_Notes字段包含的数据如“已添加项目{3/11/2011}”这些数据都不符合内部选择的条件,所以在我看来如果没有在内部选择中选择它,它对于外部选择的条件应该不是问题。但是,它试图将2011 {311转换为int并抛出错误。我确信它是在尝试将其转换为迄今为止,这就是为什么我遇到了以前的问题。

3 个答案:

答案 0 :(得分:1)

试着看这篇文章。它讨论从字符串字段中提取日期。这应该可以帮助您编写选择:

SQL: extract date from string

答案 1 :(得分:1)

尝试在语句中添加类似于此WHERE子句的内容:

WHERE CAST(SUBSTRING(Notes, CHARINDEX(Notes, 'on {') + 4, Length?) AS Date) BETWEEN StartDate And EndDate

我们的想法是通过组合SubString和CharIndex方法提取字符串的相关部分,然后将此表达式转换为日期格式,以便它可以与Between运算符一起使用。

最好的运气

第2部分更新:

由于您已经能够选择日期但不在where子句中使用它,我建议将其用作select语句,然后将其包装在另一个语句中,例如:

SELECT *
FROM
(SELECT CAST(SUBSTRING(Notes, CHARINDEX(Notes, 'on {') + 4, Length?) AS Date) AS dtmNotes)
WHERE dtmNotes BETWEEN Start And End

这只是为了说明,但在包装中包含了整个第一个select语句。

答案 2 :(得分:0)

试试这个......

假设具有嵌入日期的表名为 InventoryList ,该列名为 inv_Notes


SELECT *
FROM InventoryList i
WHERE

CAST(
substring(
i.inv_Notes,
patindex('%on {%',i.inv_Notes)  +4,
patindex('%[0-9][0-9][0-9][0-9]}%',i.inv_Notes)-patindex('%on {%',i.inv_Notes)
) as Datetime)

BETWEEN '12/1/2011' AND '12/23/2011

编辑:更具限制性地寻找“9/9999}”模式


SELECT *
FROM InventoryList i
WHERE

CAST(
substring(
i.inv_Notes,
patindex('%on {%',i.inv_Notes)  +4,
patindex('%[0-9]/[0-9][0-9][0-9][0-9]}%',i.inv_Notes)-patindex('%on {%',i.inv_Notes)
) as Datetime)

BETWEEN '12/1/2011' AND '12/23/2011