2012-04-23 27 views
3

问题:排序访问数据(格式错误的日期时间)

一些在我的表中的字段有格式错误的日期,他们在C#中使用的ToString()方法格式化但我犯了一个错字,并输入它是这样的:MM/dd/yyyy hh:mm/ss tt

现在,如果你仔细看看,你会看到MM/dd/yyyy hh:mm ---->' /'< --- ss

它被假设为''

我然后之前修复它在我的C#代码,(意味着某些值被格式化:MM/DD/YYYY HH:MM:SS TT

问题是,我试图选择日期的顺序从表中的值(我不能只是分类方式“Datefieldnamehere”),因为一些字段是在错误的格式用“/”


我试过的:

现在,我认为时间总是在同一个地方(而这对我来说很重要),我可以在时间中取出数字的子串并对它们进行排序;首先为AM然后PM

我可以为了通过MID([的ColumnName],11,2),MID([的ColumnName],14,2),MID([的ColumnName],16,2)因为每次约会无论分隔符是始终在格式M/DD/YYYY HH/MM/SS TT

所以我尝试:


(
SELECT SN, StatusCode, Time, Mid(Time,14,2) + ':'+ Mid(Time,17,2) AS TTI 
FROM OrderStatus 
WHERE StatusCode = 'Finished' and Left(Time,10) = '4/20/2012' 
AND Time LIKE '*AM' 
ORDER BY Val(Mid([Time],11,2)) DESC 
) 
UNION ALL (
SELECT SN, StatusCode, Time, Mid(Time,14,2) + ':'+ Mid(Time,17,2) AS TTI 
FROM OrderStatus 
WHERE StatusCode = 'Finished' and Left(Time,10) = '4/20/2012' 
AND Time LIKE '*PM' 
ORDER BY Val(Mid([Time],11,2)) DESC 
); 

只是为了看看日at会按小时订购,但它不会给我这个: Err

正如你可以看到它(在小时字段)01然后02然后它回到01 ...?

反正有一个类似的问题here,我已经把赏金上,如果你回答这个问题,还是这个问题,这将是了解其他情况,以及

编辑有用,你将获得赏金: 这个问题,我真的想回答如何按字符串的子串排序;对不起后期编辑我可以发誓我已经改变了这一点,说我想排序的任何字符串/日期/任何东西我想知道我可以做些什么,如: Order By Val(Mid(ColumnName,StartPos ,EndPos))

注意:该Order By给出完全错误的结果。

+0

是但不是真的......,有21000+的记录,我不能简单地调用.replace因为有/的在日期之前将年月日之间,和我不能替换子字符串中的确切位置的值,因为某些日期在本月有10/11/12(额外的数字),我想我可以做一个if(date.length == 22)和21等等陪伴,但是这真的会挫败这个问题的目的以备将来使用。我真正想知道的是如何甚至有可能通过字符串的子字符串进行排序。 – 2012-04-23 18:06:05

+0

虽然我会将它投票,但这是一个非常好的建议 – 2012-04-23 18:06:38

+0

我认为它总是更好地解决问题,然后找到一个复杂的工作方式,而不必修复它。由于这是一次性的事情,你可以使用一个临时的日期字段和一个时间字段来分割所涉及的字段。然后一个简单的替换应该很容易。 (我发现它并没有回答按字符串排序的问题,但..)) – Johanness 2012-04-23 23:03:10

回答

1

我没有表测试,但是我想给我的想法。
我将使用Left,Mid和Right函数以及CDate和CInt函数。
我将得到时间字段的最左边部分(16字节),为秒和PM/AM指示符添加“:00”。该字符串可以使用CDate转换为日期。
然后我会得到秒部分并将它们转换为一个整数。
现在顺序可以达到排序第一部分(TTI),然后第二部分(TTS)不使用UNION。
但有一个问题,有些日期包含一个月只有1个字符(4月4日和12月12日),幸运的是,我们可以使用IIF操作符为中,左,右选择正确的数字。

编辑:

SELECT 
SN, StatusCode, Time, 
IIF(Len(Time) = 22, Left(Time,16) + ':00' + Right(Time,2), Left(Time,15) + ':00' + Right(Time,2)) AS TTI, 
IIF(Len(Time) = 22, Mid(Time, 18,2), Mid(Time, 17,2)) as TTS 
FROM OrderStatus 
WHERE StatusCode = 'Finished' and Left(Time,10) = '4/20/2012' 
ORDER BY CDate(IIf(Len([Time])=22,Left([Time],16)+ ':00 ' + Right([Time],2),Left([Time],15)+ ':00 ' + Right([Time],2))) DESC , 
     CInt(IIf(Len([Time])=22,CInt(Mid([Time],18,2)),CInt(Mid([Time],17,2)))) DESC; 
+0

这是错误的用法左右是不是?左边有2个参数不是3 – 2012-04-23 19:16:04

+0

@JustinKirk你是对的。纠正。你可以试试吗? – Steve 2012-04-23 19:25:18

+0

尝试............................... – 2012-04-23 19:26:18

2

使提交日期成为实际日期字段而不是字符串。用2个更新将所有值迁移到新字段 - 一个选择所有具有旧格式的行,另一个选择新的。拖放日期的字符串列并享受正确类型的数据。

如果你真的想把它保留为字符串,至少要确保使用对排序/本地化安全的标准ISO8601格式(大约是YYYY-MM-DDTHH:MM.ssss)。

+0

有8000多行代码不是由我在c#中以字符串的形式访问这些数据,我不能简单地将其更改为日期时间或我已经。 – 2012-04-23 18:22:10

+0

我投了你的答案,因为我感谢你的注意,你是非常正确的(它应该是一个真正的日期,而不是一个字符串),但它不回答我的问题 – 2012-04-23 18:29:22

+1

谢谢。我仍然建议,如果你最终触摸这个代码,那么切换到可排序的字符串格式。 HansUp的转换看起来正是你需要的。 – 2012-04-23 18:53:20

3

我的直觉是创建一个函数,并在Access UPDATE语句中运行一次,以转换存储的值以匹配所需的格式。

快速&肮脏的功能下面应付单一和两位数月份。它需要Access 2000或更高版本。

? FixTimeData("4/20/2012 01:34/09 PM") 
4/20/2012 01:34:09 PM 
? FixTimeData("12/20/2012 01:34/09 PM") 
12/20/2012 01:34:09 PM 

Public Function FixTimeData(ByVal pIn As String) As String 
    Dim astrPieces() As String 
    Dim strOut As String 
    astrPieces = Split(pIn, " ") 
    strOut = astrPieces(0) & " " & _ 
     Replace(astrPieces(1), "/", ":") & " " & _ 
     astrPieces(2) 
    FixTimeData = strOut 
End Function 

然后UPDATE语句与此类似...

UPDATE OrderStatus 
SET time_field = FixTimeData(time_field) 
WHERE time_field Like "*/*/*/*"; 

如果您运行的ADO,而不是DAO,切换到ANSI通配符在WHERE子句中下的声明。

WHERE time_field Like "%/%/%/%"; 

或者,如果你想在同一语句要么ADO或DAO下工作使用ANSI与一致好评外卡。

WHERE time_field ALike "%/%/%/%"; 

我用time_field作为你们以前Time因为Time是保留字的字段名称。如果无法更改字段名称,请在查询中用方括号括起来。

编辑:我的目的是让您可以再排序可靠依据Right(time_field, 11)

EDIT2来修正数据:要立足于“上”分数字进行排序,看看你能不能建立在这个方法,它假定你有固定的存储日期/时间字符串:

? Left(Format(Minute("4/23/2012 04:02:40 PM"), "00"), 1) 
0 
? Left(Format(Minute("4/23/2012 04:12:40 PM"), "00"), 1) 
1 
? Left(Format(Minute("4/23/2012 04:22:40 PM"), "00"), 1) 
2 

虽然Minute()函数接受一个字符串,我可能会用CDate()字符串变换明确地向逸e /将其送至Minute()之前的时间。

所以......如果我还没有完全误入歧途...尝试这样的查询方法:

SELECT 
    Left(Format(Minute(CDate(time_field)), "00"), 1) AS upper_minute, 
    OrderStatus. * 
FROM OrderStatus 
ORDER BY 1; 
+0

这是一个很好的解决我的问题(我可以使用c#修复它非常类似),但它忽略了问题的主要观点;我如何排序列的子字符串:我所有的谷歌结果表明,我可以按左/右/中间(ColumnName,长度)或中期的情况下(ColumnName,开始,长度),但它不似乎正在工作 – 2012-04-23 18:24:55

+0

修复数据后,不'Right(time_field,11)'给你正确的排序吗? – HansUp 2012-04-23 18:28:42

+0

是的,但是,如果我尝试或找到需要按上分钟列排序,hh: - > m < - m:ss是不是可以按此排序? – 2012-04-23 18:32:47