棘手的数据输入验证SQL查询

棘手的数据输入验证SQL查询,sql,sql-server-2008,while-loop,cursor,logic,Sql,Sql Server 2008,While Loop,Cursor,Logic,我试图开发一个查询来验证用户数据输入,但我被卡住了。基本上,我们正在处理关于每日24小时合成水样的信息。用户将输入COLDATE,COLDATE是组合的结尾,并以日期时间格式存储,如2015-03-02 04:00:00.000。然后他们将进入Compstartdate,它是varchar8,看起来像03/02/15。最后,他们将进入Compstarttime,它是varchar5,看起来像04:01 别怪我,我不是这样设置的,让我们假设修复数据类型不是一个选项 我要处理的规则是,一天的Comp

我试图开发一个查询来验证用户数据输入,但我被卡住了。基本上,我们正在处理关于每日24小时合成水样的信息。用户将输入COLDATE,COLDATE是组合的结尾,并以日期时间格式存储,如2015-03-02 04:00:00.000。然后他们将进入Compstartdate,它是varchar8,看起来像03/02/15。最后,他们将进入Compstarttime,它是varchar5,看起来像04:01

别怪我,我不是这样设置的,让我们假设修复数据类型不是一个选项

我要处理的规则是,一天的Compstartdate/时间需要与前一天的COLDATE匹配。到目前为止,我只能知道如何查看COLDATEday-1天是否等于Compstartdateday。换句话说,我可以很容易地在一条记录内进行逻辑比较,但我不知道如何比较两条记录

此外,我们只讨论2000个记录,因此性能考虑并不重要,我使用的案例陈述就是证明。我的意思是,我完全可以接受包含游标或while循环的解决方案

以下是我目前掌握的情况:

SELECT S.[SAMPNO]
      ,S.[LOCCODE]
      ,S.[COLDATE]
      ,U.[Compstartdate]
      ,U.[Compstarttime]

  FROM [dbo].[SAMPLE] as S
  JOIN [dbo].[SUSERFLDS] as U
  on S.SAMPNO = U.SAMPNO

  Where 
    Case
        When DATEPART(DAY, Convert(VARCHAR(10),U.Compstartdate,101)) != 
             DATEPART(DAY, DATEADD(DAY, -1, S.COLDATE))

        Then 'Yes' 

        ELSE 'NO'

    END ='YES' 
编辑:让我试着更好地解释这个问题。如果我今天采集了一个24小时合成样本,并将该样本的相关信息输入数据库,我将输入采集合成样本的日期/时间结束以及合成开始的日期/时间。因为它是24小时合成的,所以今天样本的开始日期/时间应该等于昨天样本的结束时间日期。因此,我需要取两个具有相同LOCCODE但与COLDATE相隔一天的样本。然后查看前一个样本的COLDATE是否等于后一个样本的Compstartdate/时间

编辑2:下面是一些示例数据

create table [SAMPLE] (
  SAMPNO   int,
  LOCCODE  char(7),
  COLDATE  datetime
);

create table SUSERFLDS (
 SAMPNO        int,
 Compstartdate char(8),
 Compstarttime char(5)
);

SET DATEFORMAT mdy;


insert into [SAMPLE] values (11,'Sample1','2015-03-02 04:00:00.000');
insert into [SAMPLE] values (12,'Sample1','2015-03-03 04:00:00.000');
insert into [SAMPLE] values (13,'Sample1','2015-03-04 04:00:00.000');
insert into [SAMPLE] values (14,'Sample1','2015-03-05 04:00:00.000');

insert into SUSERFLDS values (11, '03/01/15', '04:00');
insert into SUSERFLDS values (12, '03/02/15', '04:00');
insert into SUSERFLDS values (13, '03/03/15', '05:00');
insert into SUSERFLDS values (14, '03/04/15', '04:00');
--Compstartdate/time for SAMPNO 12
--does match COLDATE for SAMPNO 11
--Compstartdate/time for SAMPNO 13 
--should match COLDATE for SAMPNO 12

我想您可能会感到困惑——没有必要在表中循环——这就是join的作用

不幸的是,SQLFiddle目前似乎有困难。这就是我要举的一个例子:

create table SAMPLE (
  SAMPNO   int,
  LOCCODE  char(1),
  LOCDESCR char(1),
  LOGBATCH char(1),
  LOGUSER  char(1),
  COLDATE  datetime
);

create table SUSERFLDS (
 SAMPNO        int,
 Compstartdate char(8),
 Compstarttime char(5)
);

SET DATEFORMAT mdy;

insert into SAMPLE values (1, 'x','x','x','x','2015-03-01 04:00:00.000');
insert into SAMPLE values (2, 'x','x','x','x','2015-03-02 04:00:00.000');
insert into SAMPLE values (3, 'x','x','x','x','2015-03-03 04:00:00.000');
insert into SAMPLE values (4, 'x','x','x','x','2015-03-04 04:00:00.000');
insert into SAMPLE values (5, 'x','x','x','x','2015-03-05 04:00:00.000');

insert into SUSERFLDS values (2, '03/02/15', '04:00');
insert into SUSERFLDS values (3, '03/04/15', '04:00');
insert into SUSERFLDS values (4, '03/05/15', '04:00');
insert into SUSERFLDS values (5, '03/06/15', '05:00');

请提出任何问题或在评论中添加澄清。

您只说前一天的日期和时间必须匹配。但是你需要匹配SAMPNO值。我猜SUSERFLDS会在第二天采集样本时输入

您的查询启动正常,只是您的引用表似乎是SUSERFLDS,所以应该是列出的第一个表。然后,您希望从具有相同样本编号、相同日期和时间的样本中匹配记录

要进行比较,您可以将SAMPNO datetime转换为与日期字符串mm/dd/yy格式相同的字符串,并从SUSERFLDS中提取要与字符串进行比较的日期部分和时间部分,或者将日期和时间字符串转换为datetime值,仅与SAMPNO datetime进行比较

使用后一个选项,查询如下:

select  U.[SAMPNO],
        U.[Compstartdate],
        U.[Compstarttime],
        S.[LOCCODE],
        S.[LOCDESCR],
        S.[LOGBATCH],
        S.[LOGUSER],
        S.[COLDATE]
from    SUSERFLDS u
left join SAMPLE  s
    on  s.SampNo  = u.SampNo
    and s.ColDate = Cast( u.CompStartdDate + ' ' + u.CompStartTime as datetime );
请注意,我使用了外部联接。也就是说,您仍然可以看到所有的SUSERFLDS条目,但其中的样本数据应该是那些日期时间不匹配的样本的null。这会立即指示日期和时间不匹配的位置。你可以加上

where  s.SampNo is null
并且您将只获得样本日期时间不匹配的SUSERFLDS条目。在这种情况下,您可以省略选择列表中的所有S.XXX字段,因为它们总是显示为NULL

然而,这并没有告诉你多少。如果你能看到实际的样本日期,但只看到那些不匹配的,不是更好吗

在这种情况下,将左侧放置以执行内部联接,并将联接条件更改为“不等于”。像这样:

select  U.[SAMPNO],
        U.[Compstartdate],
        U.[Compstarttime],
        S.[LOCCODE],
        S.[LOCDESCR],
        S.[LOGBATCH],
        S.[LOGUSER],
        S.[COLDATE]
from    SUSERFLDS u
join    SAMPLE    s
    on  s.SampNo  = u.SampNo
    and s.ColDate <> Cast( u.CompStartdDate + ' ' + u.CompStartTime as datetime );

现在您可以看到SUSERFLDS日期和时间值以及示例datetime值,但只针对不匹配的条目。这可以让您了解问题所在。

终于解决了。以下是我想要的查询:

set dateformat mdy;
With CTE1 as 
(
Select  S1.SAMPNO as SAMPNO1
        ,S1.COLDATE as COLDATE1
        ,S1.LOCCODE as LOCCODE1
        ,CAST( U1.Compstartdate +' '+ U1.Compstarttime as datetime) as Compstart1
From [SAMPLE] as S1 join
    [SUSERFLDS] as U1 on S1.SAMPNO = U1.SAMPNO
),
CTE2 as 
(
Select  S2.SAMPNO as SAMPNO2
        ,S2.COLDATE as COLDATE2
        ,S2.LOCCODE as LOCCODE2
        ,CAST( U2.Compstartdate +' '+ U2.Compstarttime as datetime) as Compstart2
From [SAMPLE] as S2 join
    [SUSERFLDS] as U2 on S2.SAMPNO = U2.SAMPNO
)
SELECT LOCCODE1
      ,SAMPNO1
      ,SAMPNO2
      ,COLDATE1
      ,COLDATE2
      ,Compstart1
From CTE1 join
        CTE2 on LOCCODE1 = LOCCODE2 and 
            COLDATE2 = DATEADD(Day, -1, COLDATE1)
Where Compstart1 != COLDATE2

如果您发现任何致命缺陷,请告诉我

我可以很容易地在一条记录内进行逻辑比较,但我不知道如何比较两条记录。你的意思是你可以比较日期,但也需要比较时间吗?虽然我确实需要比较日期和时间元素,但这不是我所说的比较两个记录的意思。我的意思是,我不知道如何将一天的数据与前一天的数据进行比较,前一天的数据将作为单独的记录/行显示在联接表中。我假设它是SQL Server。什么版本?是SQL server 2008。您知道Compstartdate和Compstarttime是否始终是有效值—有效日期和有效时间?如果你能假设他们会正确转换,那就有区别了。我喜欢你的答案,它非常彻底,但我担心你可能误解了我的问题。我试图找到一天的Compstartdate/时间与前一天的COLDATE不匹配的实例。Compstartdate/时间在SUSERFLD中
S表和COLDATE是示例表。这两个表由SAMPNO关联。让我们看看是否可以进一步简化这个问题。每天都有一个新的样品,它得到一个独特的SAMPNO。每个样品都有一个COLDATE,它是24小时合成的终点。每个示例还具有24小时合成开始的日期和时间字段。从逻辑上讲,今天样本的开始部分必须与昨天样本的结束部分相同,对吗。因此,我试图在数据输入中查找开始和结束日期/时间不匹配的错误。清晰如泥,对吗?你是说每个样本条目都有几个SUSERFLDS条目?你只是为了确保其中有一个条目的日期和时间与样本条目的日期和时间相同吗?我在底部编辑了我的帖子。我添加了一些解释,希望能解决这个问题。为什么不创建一些示例数据呢?每个表只有几行,数据与您要查找的内容相匹配,而另一行与您不匹配。对不起,我已经测试过了,但它没有给出我要查找的内容。我需要将今天的示例开始日期/时间与昨天的结束日期/时间进行比较,并找到由于数据输入错误而不相等的实例。从逻辑上讲,今天的样本24小时合成从昨天的样本结束时开始。此外,LOCCODE和LOCDESC将是今天和昨天样本中唯一相同的字段。
set dateformat mdy;
With CTE1 as 
(
Select  S1.SAMPNO as SAMPNO1
        ,S1.COLDATE as COLDATE1
        ,S1.LOCCODE as LOCCODE1
        ,CAST( U1.Compstartdate +' '+ U1.Compstarttime as datetime) as Compstart1
From [SAMPLE] as S1 join
    [SUSERFLDS] as U1 on S1.SAMPNO = U1.SAMPNO
),
CTE2 as 
(
Select  S2.SAMPNO as SAMPNO2
        ,S2.COLDATE as COLDATE2
        ,S2.LOCCODE as LOCCODE2
        ,CAST( U2.Compstartdate +' '+ U2.Compstarttime as datetime) as Compstart2
From [SAMPLE] as S2 join
    [SUSERFLDS] as U2 on S2.SAMPNO = U2.SAMPNO
)
SELECT LOCCODE1
      ,SAMPNO1
      ,SAMPNO2
      ,COLDATE1
      ,COLDATE2
      ,Compstart1
From CTE1 join
        CTE2 on LOCCODE1 = LOCCODE2 and 
            COLDATE2 = DATEADD(Day, -1, COLDATE1)
Where Compstart1 != COLDATE2