【问题标题】:C# Unable to show data even the date is fall within the date range即使日期在日期范围内,C#也无法显示数据
【发布时间】:2017-01-05 17:43:56
【问题描述】:

我正在使用 C# Window 应用程序通过使用 SQL 查询从 Microsoft Access 中提取数据进行一些检查。

我有 2 个表要比较并选择数据。

  • 表 1:USER_OF_RUN 由 StartDate 和 EndDate 组成
  • 表 2:我需要加入表 1 并拉出的 USERINFO StartDate 和 EndDate 表的日期范围内的数据。

如果我的表 1 的 StartDate 和 EndDate 设置为 2016 年 1 月 1 日至 2017 年 12 月 31 日,则所有数据都是正确的。但是,当范围设置为例如 22/12/2016 到 31/12/2017 时,我想要提取的数据来自日期 3/1/2017,该日期介于日期范围之间,但不知何故数据是空的。

我很好奇我的查询是错误的还是我遗漏了一些语法。

这是我的 SQL 查询:

SELECT 
    FORMAT(A.CHECKTIME,'dd/mm/yyyy') AS CHECKTIME,
    A.USERID AS USERID, 
    B.NAME AS NAME, 
    B.BADGENUMBER AS BADGENUMBER, 
    C.NUM_OF_RUN_ID, 
    D.NAME AS DEPT, 
    DEFAULTDEPTID 
FROM ((((CHECKINOUT A ) 
    LEFT JOIN USERINFO B 
        ON A.USERID = B.USERID ) 
    LEFT JOIN USER_OF_RUN C 
        ON A.USERID = C.USERID ) 
    LEFT JOIN NUM_RUN D 
        ON C.NUM_OF_RUN_ID = D.NUM_RUNID ) 
WHERE 
    Format(A.CHECKTIME, 'dd/mm/yyyy') IN (Format('03/01/2017', 'dd/mm/yyyy'), Format(DateAdd('d', 1, Format('03/01/2017', 'dd/mm/yyyy')), 'dd/mm/yyyy')) 
    AND Format('03/01/2017', 'dd/mm/yyyy') BETWEEN Format(C.STARTDATE, 'dd/mm/yyyy') AND Format(C.ENDDATE, 'dd/mm/yyyy') 
    AND DEFAULTDEPTID = 4 
    AND BADGENUMBER = '7092'
ORDER BY A.USERID DESC, CHECKTIME asc 

UNION ALL 

SELECT 
    distinct '', 
    USERID, 
    NAME, 
    BADGENUMBER, 
    '',
    '',
    '' 
FROM USERINFO 
WHERE userid NOT IN 
    (SELECT DISTINCT A.USERID AS USERID 
     FROM ((((CHECKINOUT A) 
         LEFT JOIN USERINFO B 
             ON A.USERID = B.USERID ) 
         LEFT JOIN USER_OF_RUN C 
             ON A.USERID = C.USERID ) 
         LEFT JOIN NUM_RUN D 
             ON C.NUM_OF_RUN_ID = D.NUM_RUNID ) 
     WHERE Format (A.CHECKTIME, 'dd/mm/yyyy') = Format('03/01/2017', 'dd/mm/yyyy') 
         AND Format('03/01/2017', 'dd/mm/yyyy') BETWEEN Format(C.STARTDATE, 'dd/mm/yy') AND Format(C.ENDDATE, 'dd/mm/yyyy')) 
         AND DEFAULTDEPTID = 4 
         AND BADGENUMBER = '7092'

【问题讨论】:

  • 您的查询在这样的单行上是不可读的——即使不是这样,它也比它需要的复杂得多。请将其减少为 minimal 查询。 (您是否尝试过不使用连接进行查询?)
  • 我的印象是您将日期存储为字符串。我说的对吗?
  • 正如史蒂夫暗示的那样,将日期存储为字符串是一个非常非常糟糕的主意 - 特别是考虑到您没有以可排序的顺序存储它们! (在词汇上,字符串“01/01/2020”出现在“10/01/2016”之前——但你不希望这样......)
  • 补充@JonSkeet 所说的,如果您将日期存储为字符串,那么您应该在比较它们之前将它们转换为日期
  • @MarcusZac:嗯,就是这样——就像字符串“abc”出现在“bcd”之前一样。当您比较字符串 时,您基本上首先查看第一个字符...并且“0”在“1”之前。 (比这复杂一点,但从根本上说明了问题。)

标签: c# sql ms-access


【解决方案1】:

如果你不觉得可以减少查询来调试它,至少把日期部分弄对:

SELECT 
    A.CHECKTIME,
    A.USERID, 
    B.NAME, 
    B.BADGENUMBER, 
    C.NUM_OF_RUN_ID, 
    D.NAME AS DEPT, 
    DEFAULTDEPTID 
FROM ((((CHECKINOUT A ) 
    LEFT JOIN USERINFO B 
        ON A.USERID = B.USERID ) 
    LEFT JOIN USER_OF_RUN C 
        ON A.USERID = C.USERID ) 
    LEFT JOIN NUM_RUN D 
        ON C.NUM_OF_RUN_ID = D.NUM_RUNID ) 
WHERE 
    A.CHECKTIME = #2017/01/03# 
    AND 
    #2017/01/03# BETWEEN C.STARTDATE AND C.ENDDATE 
    AND 
    DEFAULTDEPTID = 4 
    AND 
    BADGENUMBER = '7092'
ORDER BY A.USERID DESC, A.CHECKTIME ASC

UNION ALL 

SELECT 
    DISTINCT 
    '', 
    USERID, 
    NAME, 
    BADGENUMBER, 
    '',
    '',
    '' 
FROM USERINFO 
WHERE USERID NOT IN 
    (SELECT DISTINCT A.USERID AS USERID 
     FROM ((((CHECKINOUT A) 
         LEFT JOIN USERINFO B 
             ON A.USERID = B.USERID ) 
         LEFT JOIN USER_OF_RUN C 
             ON A.USERID = C.USERID ) 
         LEFT JOIN NUM_RUN D 
             ON C.NUM_OF_RUN_ID = D.NUM_RUNID ) 
     WHERE 
         A.CHECKTIME = #2017/01/03# 
         AND 
         #2017/01/03# BETWEEN C.STARTDATE AND C.ENDDATE 
         AND 
         DEFAULTDEPTID = 4 
         AND 
         BADGENUMBER = '7092'

如果您的日期字段包含时间部分,请将其包装在 DateValueFix 中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多