Sql 选择“在日期之间查询”,仅选择“开始”和“结束”字段之间的项目

Sql 选择“在日期之间查询”,仅选择“开始”和“结束”字段之间的项目,sql,sql-server,date,Sql,Sql Server,Date,我有两个表,我将用于跟踪目的,一个日期表和一个项目表。日期表用于跟踪跟踪id的开始和结束日期。项目表是在id的特定日期提取的项目数量。id是这两个表之间的外键 我想做的是,用项目id的GROUP BY对项目进行求和,但仅通过根据提取项目的日期是否在跟踪id的开始日期和结束日期之间对项目进行求和 日期表 id开始日期结束日期 1 2014-01-01空 2 2014-01-01 2014-01-02 3 2014-01-25零 项目表 id项目日期 1 3 2014-01-01 1

我有两个表,我将用于跟踪目的,一个日期表和一个项目表。日期表用于跟踪跟踪id的开始和结束日期。项目表是在id的特定日期提取的项目数量。id是这两个表之间的外键

我想做的是,用项目id的GROUP BY对项目进行求和,但仅通过根据提取项目的日期是否在跟踪id的开始日期和结束日期之间对项目进行求和

日期表 id开始日期结束日期 1 2014-01-01空 2 2014-01-01 2014-01-02 3 2014-01-25零 项目表 id项目日期 1 3 2014-01-01 1 5 2014-01-02 1 5 2014-01-26 2 2 2014-01-01 2 3 2014-01-05 2 2 2014-01-26 3 2 2014-01-01 3 3 2014-01-05 3 2 2014-01-26 到目前为止我已经有了SQL,但是我不知道从这里添加什么

SELECT 
    a.id, 
    SUM(items) 
FROM 
    ww_test.dbo.items a
INNER JOIN ww_test.dbo.dates b ON
    a.id = b.id
WHERE
    a.date >= '2014-01-01' AND a.date <= '2014-01-30'
GROUP BY 
    a.id
ORDER BY 
    a.id
选择
a、 身份证,
总数(项目)
从…起
ww_test.dbo.a项
内部连接ww_test.dbo.b上的日期
a、 id=b.id
哪里

a、 日期>='2014-01-01'和a.date我想你要做的是比较
数据表的
开始日期和
结束日期之间的日期

将查询更改为以下内容,然后重试

SELECT 
    a.id, 
    SUM(items) 
FROM 
    ww_test.dbo.items a
    INNER JOIN ww_test.dbo.dates b ON a.id = b.id
WHERE
    a.date >= ISNULL(b.start_date, GETDATE()) 
    AND a.date <= ISNULL(b.end_date, GETDATE())
GROUP BY a.id
ORDER BY a.id
选择
a、 身份证,
总数(项目)
从…起
ww_test.dbo.a项
a.id=b.id上的内部连接ww_test.dbo.dates b
哪里
a、 日期>=ISNULL(b.start\u date,GETDATE())

a.date查询的问题是条件部分。 此外,由于需要根据Dates表中定义的条件检索数据,所以不必显式地硬编码该条件。 假设结束日期可以为null或有值,则可以使用 查询:


首先,我强烈建议您停止在日期范围中使用
NULL
来表示“无结束日期”,而是使用哨兵值,如
9999-12-31
。这样做的原因主要是性能,其次是查询的简单性——这对您自己编写查询以及您或以后需要维护查询的其他人都有好处。在前端或中间层代码中,将日期范围与
Null
9999-12-31
进行比较没有什么区别,事实上,简化代码的一些好处与SQL中的相同。我的推荐基于10年以上的全职专业SQL查询编写经验

要按原样修复您的查询,我认为这会起作用:

SELECT 
   a.id, 
   ItemsSum = SUM(items)
FROM 
   ww_test.dbo.items a
   INNER JOIN ww_test.dbo.dates b
      ON a.id = b.id
      AND a.date >= Coalesce(b.start_date, 0)
      AND a.date <= Coalesce(b.end_date, '99991231')
WHERE
   a.date >= '20140101'
   AND a.date <= '20140130'
GROUP BY 
   a.id
ORDER BY 
   a.id
;
您会发现,如果数据集变大,必须在其中放入
合并
IsNull
,将严重影响性能。使用
子句也无济于事:

INNER JOIN ww_test.dbo.dates b
   ON a.id = b.id
   AND (a.date >= b.start_date OR b.start_date IS NULL)
   AND (a.date <= b.end_date OR b.end_date IS NULL)
最后一件事:请注意,日期格式“yyy-mm-dd”不是区域性安全的

SET LANGUAGE FRENCH;
SELECT Convert(datetime, '2014-01-30'); -- fails with an error
SQL Server中datetime的唯一不变区域性安全格式是:

yyyymmdd
yyyy-mm-ddThh:mm:ss

有趣的是,我从来没有听说过关于零结束日期的想法。非常感谢。明天我将向我们的DBA提出这个问题,因为我将部署此查询的实际库存和跟踪数据库位于几十万条记录中的某个位置,这些记录需要分解为我在原始帖子中提到的id组。很抱歉延迟,@ErikE。我的DBA和我今晚能够实施您的所有建议。非常感谢您提供的所有附加信息!
SELECT 
    a.id, 
    SUM(items) 
FROM 
    ww_test.dbo.items a
INNER JOIN ww_test.dbo.dates b ON
    a.id = b.id
where (b.end_date is not null and a.date between b.start_date and b.end_date)
or (b.end_date is null and a.date >= b.start_date)
GROUP BY 
    a.id
ORDER BY 
    a.id
SELECT 
   a.id, 
   ItemsSum = SUM(items)
FROM 
   ww_test.dbo.items a
   INNER JOIN ww_test.dbo.dates b
      ON a.id = b.id
      AND a.date >= Coalesce(b.start_date, 0)
      AND a.date <= Coalesce(b.end_date, '99991231')
WHERE
   a.date >= '20140101'
   AND a.date <= '20140130'
GROUP BY 
   a.id
ORDER BY 
   a.id
;
INNER JOIN ww_test.dbo.dates b
   ON a.id = b.id
   AND a.date >= b.start_date
   AND a.date <= b.end_date
INNER JOIN ww_test.dbo.dates b
   ON a.id = b.id
   AND (a.date >= b.start_date OR b.start_date IS NULL)
   AND (a.date <= b.end_date OR b.end_date IS NULL)
INNER JOIN ww_test.dbo.dates b
   ON a.id = b.id
   AND a.date >= b.start_date
   AND a.date < b.end_date -- no equal sign now
SET LANGUAGE FRENCH;
SELECT Convert(datetime, '2014-01-30'); -- fails with an error
yyyymmdd
yyyy-mm-ddThh:mm:ss