我在T-SQL中自学成才,如果我用一个简单的答案问一个问题,请原谅我,但我已经知道了我的知识,我的互联网搜索我没有教我正在寻找的东西......
我有两张桌子,我正在使用:
tbl_A (exit)
----------------------------
id_num | exit_dte
----------------------------
100001 | 2001-01-15
100002 | 2001-01-31
100003 | 2001-06-03
tbl_B (period)
---------------------------------------------
period_id | period_start_dte | period_end_dte
---------------------------------------------
1 | 2001-01-01 | 2001-01-31
2 | 2001-07-01 | 2001-07-31
系统界面允许数据用户将他们想要的任何日期放入tbl_A.exit_dte,尽管他们的(未经写入的)业务策略声明他们不应该在该列中放置一个不会下降的日期在tbl_B中的记录的period_start_dte和period_end_dte之间。我需要找到任何不在period_id的开头和结尾之间的exit_dte。
我的第一步是准备一份不同的现有tbl_A.exit_dte值列表。我知道怎么做:
Select distinct tbl_A.exit_dte from tbl_A
我不知道怎么做,但我想我想做的是使用游标循环遍历此列表的值,并为每个值确定它是否介于开始之间以tbl_B为期的结束日期。如果它在一个期间日期范围内,我将显示"在范围&#34 ;;否则,我会显示"错误" (我理解描述符是不相关的。)
2001-01-15 | In Range (matches tbl_B.period_id = 1)
2001-01-31 | In Range (matches tbl_B.period_id = 1)
2001-06-03 | Error
以下是我为了获得理想结果所尝试的内容:
Declare @ques_dte datetime
Declare @Getid cursor
Set @Getid = CURSOR FOR
Select distinct exit_dte
from tbl_A
Open @Getid
Fetch NEXT
from @Getid into @ques_dte
while @@FETCH_STATUS = 0
Begin
select
@ques_dte as checked_date
, case
when tbl_B.period_id is not null then 'In Range'
else 'Error' end as Date_Period_Check
from tbl_B
where @ques_dte between tbl_B.period_start_dte and tbl_B.period_end_dte
Fetch NEXT
From @Getid INTO @ques_dte
END
Close @Getid
Deallocate @Getid
因此,当我运行查询时,查询并不会爆炸(总是一个好兆头),但有几个问题。首先,SSMS中的结果使它看起来像是为每个@ques_dte值(可能是)运行一个不同的查询,而不是一组长的结果。我确定这是由于我对BEGIN,FETCH,END的CURSOR操作的不正确理解。
其次,查询显示@ques_dte 匹配一个tbl_B.period_id,并显示" In Range"值,那些不匹配的@ques_dte,不显示@ques_dte或"错误"值 - 它只是一个空记录集。我对此感到困惑。
第三,(这可能是因为我不耐烦而且不理解基于集合的SQL操作之间的区别,不管这是什么......)查询似乎需要很长时间才能运行。在我的生产环境中,tbl_B中有164条记录,而来自tbl_A的不同查询中有1011条记录。这些似乎是小数字,但查询需要29秒才能完成。
我欢迎专家的反馈和建议。我不太关心执行时间 - 我可以延迟生活 - 但如果有人愿意在我的前两个问题上教育我,我会非常感激。
答案 0 :(得分:1)
对我而言,就像一个简单的左连接就可以了:
SELECT id_num, exit_dte, period_id
FROM [exit]
LEFT JOIN period
ON exit_dte > period_statt_dte
AND exit_dte < period_end_dte
您将获得范围内的日期范围的period_id,以及不包含范围的日期的null。
如果要显示“在范围内”和“错误”,可以使用大小写:
SELECT exit_dte,
CASE WHEN period_id IS NOT NULL THEN
'In Range'
ELSE
'Error'
END
FROM [exit]
LEFT JOIN period
ON exit_dte > period_statt_dte
AND exit_dte < period_end_dte
答案 1 :(得分:1)
这将是您所需要的,它将基于一组数据而不是在第二个表的每一行(如光标所做的那样)逐个进行:
select id_num, exit_dte
from table1 t1 left join table2 t2 on t1.exit_dte between period_start_dte and period_end_dte
where t2.period_id is null