如何提取 table 中只有开始和结束日期值的日期范围之间的数据?
How to extract data between a date range which has only start and end date values in the table?
我有一个table,有10+万条记录,结构如下-
Store ID
Item ID
item_active_Date
item_inactive_date
NY0001
FMC0001
2021-10-30
2021-11-30
NY0001
FMC0002
2021-01-10
2021-06-14
NY0002
FMC0003
2021-09-01
2021-09-10
NY0002
FMC0004
2021-01-01
2021-03-31
NY0003
FMC0005
2021-04-01
2021-05-30
NY0003
FMC0006
2021-06-02
2021-06-24
NY0004
FMC0007
2021-01-02
Null
需要确定 item_ID 在给定日期范围内可用。只有 item_active 和 item_inactive 日期可用。
考虑在“2021-06-15”和“2021-11-25”之间可用的 item_ID。预期结果如下(当item_inactive日期不可用时视为今天)-
Store ID
Item ID
item_active_Date
item_inactive_date
NY0001
FMC0001
2021-10-30
2021-11-30
NY0002
FMC0003
2021-09-01
2021-09-10
NY0003
FMC0006
2021-06-02
2021-06-24
NY0004
FMC0007
2021-01-02
Null
我相信按照这些思路应该可行:
SELECT item_ID FROM my_table
WHERE item_active_date <= $endDate
AND (item_inactive_date IS NULL
OR item_inactive_date > $startDate);
虽然您需要确保您的 SQL 引擎将这些不等式中的值解释为日期,而不是字符串,因为您的 table 使用的格式在月和月之间有天数年.
你可以这样做:
SELECT * FROM Sample
WHERE
item_active_Date BETWEEN '2021-06-15' and '2021-11-25'
OR item_inactive_date BETWEEN '2021-06-15' and '2021-11-25'
OR item_active_Date IS NULL
根据评论更新
Consider the scenario where for an item_id active_date = '2021-06-01'
and inactive_date = '2021-11-29'. This should also be part of the
result as the item was 'ACTIVE' between our query date range
如果我正确理解了您的要求,将很难获得未在日期范围内记录(或跟踪)的结果(除非有其他标志或列可以处理)。例如,如果项目在给定开始日期前一天处于活动状态,并在结束日期后标记为不活动,则它不会显示在结果中,因为没有每天监控项目的记录 activity.同样,没有无效日期的项目(假设它们仍然有效)也会有同样的问题。
因此,为了获得准确的结果并使查询更容易,您需要根据活动和非活动日期重新生成项目活动。所以,我们需要先填补日期空白。以项目 FMC0003
为例,它在 2021-09-01
上处于活动状态,在 '2021-09-10' 上处于非活动状态。我们将需要重新生成它以记录从活动日期到非活动日期的每个日期。因此,在我们的示例中,项目 FMC0003
将有 10 条记录。这将应用于 table.
中的所有记录
示例:
;WITH CTE AS (
SELECT
[Store ID],
[Item ID],
item_active_Date ,
ISNULL(item_inactive_date, GETDATE()) item_inactive_date
FROM Sample s
UNION ALL
SELECT
c.[Store ID],
c.[Item ID],
DATEADD(DAY, 1, c.item_active_Date) ,
c.item_inactive_date
FROM CTE c
WHERE
DATEADD(DAY, 1, c.item_active_Date) <= c.item_inactive_date
)
SELECT *
FROM Sample
WHERE EXISTS
(
SELECT * FROM CTE c
WHERE c.item_active_Date BETWEEN '2021-06-15' AND '2021-11-25'
)
ORDER BY [Store ID], [Item ID], item_active_Date
OPTION (MAXRECURSION 0)
找到重叠区间的正确方法是比较一个人的开始和另一个人的结束,另一个人的开始和第一个人的结束。
这比使用复杂的 OR
条件要高效得多,因为您正在执行直线范围查找。您的设置确实有一个缺点,即 item_inactive_date
可以为空,因此您需要在 item_active_Date
上建立索引。
SELECT *
FROM YourTable t
WHERE t.item_active_Date < '2021-11-25'
AND (t.item_inactive_date IS NULL OR t.item_inactive_date > '2021-06-15');
您可能需要根据您想要的逻辑将 <
调整为 <=
等
我有一个table,有10+万条记录,结构如下-
Store ID | Item ID | item_active_Date | item_inactive_date |
---|---|---|---|
NY0001 | FMC0001 | 2021-10-30 | 2021-11-30 |
NY0001 | FMC0002 | 2021-01-10 | 2021-06-14 |
NY0002 | FMC0003 | 2021-09-01 | 2021-09-10 |
NY0002 | FMC0004 | 2021-01-01 | 2021-03-31 |
NY0003 | FMC0005 | 2021-04-01 | 2021-05-30 |
NY0003 | FMC0006 | 2021-06-02 | 2021-06-24 |
NY0004 | FMC0007 | 2021-01-02 | Null |
需要确定 item_ID 在给定日期范围内可用。只有 item_active 和 item_inactive 日期可用。
考虑在“2021-06-15”和“2021-11-25”之间可用的 item_ID。预期结果如下(当item_inactive日期不可用时视为今天)-
Store ID | Item ID | item_active_Date | item_inactive_date |
---|---|---|---|
NY0001 | FMC0001 | 2021-10-30 | 2021-11-30 |
NY0002 | FMC0003 | 2021-09-01 | 2021-09-10 |
NY0003 | FMC0006 | 2021-06-02 | 2021-06-24 |
NY0004 | FMC0007 | 2021-01-02 | Null |
我相信按照这些思路应该可行:
SELECT item_ID FROM my_table
WHERE item_active_date <= $endDate
AND (item_inactive_date IS NULL
OR item_inactive_date > $startDate);
虽然您需要确保您的 SQL 引擎将这些不等式中的值解释为日期,而不是字符串,因为您的 table 使用的格式在月和月之间有天数年.
你可以这样做:
SELECT * FROM Sample
WHERE
item_active_Date BETWEEN '2021-06-15' and '2021-11-25'
OR item_inactive_date BETWEEN '2021-06-15' and '2021-11-25'
OR item_active_Date IS NULL
根据评论更新
Consider the scenario where for an item_id active_date = '2021-06-01' and inactive_date = '2021-11-29'. This should also be part of the result as the item was 'ACTIVE' between our query date range
如果我正确理解了您的要求,将很难获得未在日期范围内记录(或跟踪)的结果(除非有其他标志或列可以处理)。例如,如果项目在给定开始日期前一天处于活动状态,并在结束日期后标记为不活动,则它不会显示在结果中,因为没有每天监控项目的记录 activity.同样,没有无效日期的项目(假设它们仍然有效)也会有同样的问题。
因此,为了获得准确的结果并使查询更容易,您需要根据活动和非活动日期重新生成项目活动。所以,我们需要先填补日期空白。以项目 FMC0003
为例,它在 2021-09-01
上处于活动状态,在 '2021-09-10' 上处于非活动状态。我们将需要重新生成它以记录从活动日期到非活动日期的每个日期。因此,在我们的示例中,项目 FMC0003
将有 10 条记录。这将应用于 table.
示例:
;WITH CTE AS (
SELECT
[Store ID],
[Item ID],
item_active_Date ,
ISNULL(item_inactive_date, GETDATE()) item_inactive_date
FROM Sample s
UNION ALL
SELECT
c.[Store ID],
c.[Item ID],
DATEADD(DAY, 1, c.item_active_Date) ,
c.item_inactive_date
FROM CTE c
WHERE
DATEADD(DAY, 1, c.item_active_Date) <= c.item_inactive_date
)
SELECT *
FROM Sample
WHERE EXISTS
(
SELECT * FROM CTE c
WHERE c.item_active_Date BETWEEN '2021-06-15' AND '2021-11-25'
)
ORDER BY [Store ID], [Item ID], item_active_Date
OPTION (MAXRECURSION 0)
找到重叠区间的正确方法是比较一个人的开始和另一个人的结束,另一个人的开始和第一个人的结束。
这比使用复杂的 OR
条件要高效得多,因为您正在执行直线范围查找。您的设置确实有一个缺点,即 item_inactive_date
可以为空,因此您需要在 item_active_Date
上建立索引。
SELECT *
FROM YourTable t
WHERE t.item_active_Date < '2021-11-25'
AND (t.item_inactive_date IS NULL OR t.item_inactive_date > '2021-06-15');
您可能需要根据您想要的逻辑将 <
调整为 <=
等