表类别
+----+--------+----------+------------+
| ID | Active | Category | Effective |
+----+--------+----------+------------+
| 1 | FALSE | A | 1/29/2009 |
| 1 | FALSE | B | 5/13/2014 |
| 1 | TRUE | B | 9/21/2017 |
| 2 | FALSE | B | 3/4/2010 |
| 2 | TRUE | A | 2/19/2016 |
| 3 | FALSE | A | 10/15/2015 |
| 3 | TRUE | B | 8/12/2017 |
+----+--------+----------+------------+
表运行时
+----+------------+
| ID | RunDate |
+----+------------+
| 1 | 6/14/2015 |
| 1 | 9/14/2015 |
| 1 | 10/4/2016 |
| 2 | 5/1/2014 |
| 2 | 9/21/2016 |
| 3 | 3/12/2016 |
| 3 | 12/14/2017 |
+----+------------+
我正在尝试仅选择那些有{rundate}的ID
,而Category
A是有效的时间点。所以ID
1不应该在输出中,因为即使它有A类,它的rundate也是在B类生效之后。
预期产出
+----+
| ID |
+----+
| 2 |
| 3 |
+----+
尝试:
SELECT DISTINCT
RT.ID
FROM Category C
INNER JOIN Runtime RT
ON C.ID=RT.ID
WHERE 1=1
AND C.Category='A'
AND RT.rundate >= C.effective
ORDER BY RT.ID
然而,这并不考虑中间变化,只是根据每个ID的任何有效日期是否在该日期之前选择结果
答案 0 :(得分:0)
- 请尝试此查询
;with cte_category(Id, Effective,Rundate)
AS
(
SELECT c.id, max(c.effective)effective, max(r.rundate)rundate
FROM Category c
INNER JOIN runtime r on r.id = c.id
WHERE r.rundate>c.effective
GROUP BY c.id
)
SELECT DISTINCT t1.id
FROM cte_category t1
INNER JOIN cte_category t2
ON t1.id > t2.Id
AND t2.Effective < t1.Rundate
ORDER BY t1.ID
答案 1 :(得分:0)
样本数据准备
declare @category table ( ID int, Active varchar(10), Category char(1), Effective date)
insert into @category
values (1, 'FALSE', 'A', '20090129')
, (1, 'FALSE', 'B', '20140513'), (1, 'TRUE ', 'B', '20170921')
, (2, 'FALSE', 'B', '20100304'), (2, 'TRUE ', 'A', '20160219')
, (3, 'FALSE', 'A', '20151015'), (3, 'TRUE ', 'B', '20170812')
, (4, 'FALSE', 'B', '20151015'), (4, 'FALSE ', 'A', '20170812')
, (4, 'True ', 'A', '20180812')
, (3, 'TRUE ', 'A', '20270812')
declare @runtime table (ID int, RunDate date)
insert into @runtime
values (1, '20150614')
, (1, '20150914'), (1, '20161004'), (2, '20140501')
, (2, '20160921'), (3, '20160312'), (3, '20171214')
我认为您的主要问题是具有相同值的连续类别。您需要对这些值进行分组,并找到每个此类组的最小生效日期。这是cte
部分所做的。然后只需连接两个表来获得预期的输出。
;with cte as (
select
ID, Category, Effective = min(Effective)
, EndDate = isnull(lead(min(Effective)) over (partition by ID order by min(Effective)), '99991231')
from (
select
*, grp = row_number() over (partition by ID order by Effective)
- row_number() over (partition by ID, Category order by Effective)
from
@category
) t
group by ID, Category, grp
)
select
r.ID
from
@runtime r
join cte c on r.ID = c.ID and r.RunDate >= c.Effective and r.RunDate < c.EndDate
where
c.Category = 'A'