我有一个单独的列一年和一个月在我的数据库表称为日志,我想检索日志之间的2个日期,如下所示:
因此,如果我说检索从01/01/2018
到上个月的日志,即02/01/2021
,那么它应该检索所有的日志,但是我没有得到下面查询的任何结果:
select COUNT(*)
from Logs
where ((LogYear >= YEAR('01/01/2018') and LogMonth >=Month('01/01/2018')) and (LogYear <=YEAR('02/01/2021') and LogMonth < =Month('02/01/2021')))
输出:0 records
当我运行这个查询时,我得到一个0计数,尽管我有全年的数据。
这个查询有什么问题?
样本数据:
LogID LogYear LogMonth
1 2018 1
2 2018 2
3 2018 3
4 2018 4
我正在尝试从1-Jan-2018 to 1-February-2021
检索数据。
你不能通过比较一个日期的组成部分来比较它,你必须建立一个合适的日期,然后再比较它们。不幸的是,这是不可划分的,即无法使用索引,您最好存储实际日期而不是日期组件。
作为题外话,为了避免意外行为,总是使用明确的日期格式。
正如您提到的,您正在传递来自c#的值,只需确保将SqlParameter类型设置为date
而不是datetime
,以避免任何可能的时间组件问题。
declare @Logs table (LogId int, LogYear int, LogMonth int);
declare @StartDate date = '01 Jan 2018', @EndDate date = '01 Feb 2021';
insert into @Logs (LogID, LogYear, LogMonth)
values
(1, 2018, 1),
(2, 2018, 2),
(3, 2018, 3),
(4, 2018, 4),
(5, 2021, 2),
(6, 2021, 3);
SELECT COUNT(*)
FROM @Logs
WHERE DATEFROMPARTS(LogYear, LogMonth, 1) >= @StartDate
AND DATEFROMPARTS(LogYear, LogMonth, 1) <= @EndDate;
示例数据(调整以检查结束情况)产生5的结果,因为记录id 5在窗口中,而id 6不在。
我认为您需要首先以有序形式获得日期,通过转换为DATETIME
或INT
。
下面是INT
的例子:
WITH Logs2 (ID, LogDate) AS (
SELECT ID, ((LogYear * 10000) + (LogMonth * 100) + LogDay)
FROM Logs
)
SELECT COUNT(*)
FROM Logs2
WHERE (LogDate >= 20180101) AND (LogDate < 20210201)
当然更好的方法是将3列转换为DATETIME
,DATETIME2
或DATETIMEOFFSET
。
试试这个:
DECLARE @DateFrom datetime = '01/01/2018'
, @DateTo datetime = '02/01/2021'
SELECT
COUNT(*)
FROM Logs
WHERE LTRIM(LogYear*100 + LogMonth)
BETWEEN CONVERT(varchar(6), @DateFrom , 112)
AND CONVERT(varchar(6), @DateTo , 112)
您检查过DATEFORMAT ->SET DATEFORMAT (Transact-SQL)
如果可能的话,我还建议使用ISO格式的日期值来消除任何区域问题,所以
where ((LogYear >= YEAR('20180101') and LogMonth >=Month('20180101')) and (LogYear <=YEAR('20210201') and LogMonth < =Month('20210201')))
select COUNT(*)
from Logs
where (LogYear between 2018 and 2020)
or (logyear=2021 and logMonth <= 2)