【问题标题】:SQL Server - loop through temp table and calculate multiple values to insert rows into second tableSQL Server - 遍历临时表并计算多个值以将行插入第二个表
【发布时间】:2015-02-03 19:32:55
【问题描述】:

我有一个临时表 #TEMP1,它会拉回患者的下一个治疗日期以及给定日期范围内计划治疗的总数。临时表中有一个值,它给出了每次治疗之间的最短天数。

我需要做的是确定下一个治疗日期,确定在下一个治疗日期之后有多少计划治疗,并用计划日期填充第二个临时表 #TEMP2。

例如,在#TEMP1 中,包含以下数据:

patient    next_tx_dt  planned_tx_cnt   min_days_bt   start_range  end_range
PATIENT_1  2/15/2015   4                28            2/1/2015     6/1/2015
PATIENT_2  2/05/2015   9                12            2/1/2015     6/1/2015
PATIENT_3  5/17/2015   1                112           2/1/2015     6/1/2015           

我想遍历#TEMP1 并为每一行计算计划治疗的日期。因此,一行可以循环一次 (PATIENT_3) 或九次 (PATIENT_2),每个循环都会在 #TEMP2 中生成一个新行。

在成功循环后,PATIENT_1 在#TEMP2 中会产生以下结果:

pat_id      planned_tx_dt   planned_tx_cnt
PATIENT_1   2/15/2015       1
PATIENT_1   3/15/2015       2
PATIENT_1   4/12/2015       3
PATIENT_1   5/10/2015       4

PATIENT_2 将有 9 行,而 PATIENT_3 在#TEMP2 中将只有 1 行。

是否可以在 SQL Server 2008 中执行此操作?在使用行数之前我已经完成了非常基本的循环,但这在技术上并没有循环通过一个表,所以我不确定如何开始或者是否有可能(我没有很多高级写作经验SQL 代码)。

【问题讨论】:

  • 在您的#TEMP2 示例数据集中,您如何根据#TEMP1 中的数据计算planned_tx_dt
  • 在我的示例中,我只是手动计算了日期,但我认为对于查询,它必须涉及将#TEMP1.planned_tx_cnt 设置为变量,然后使用某种循环来计算每一行?例如,SET @TX_CNT = #TEMP1.planned_tx_cnt。
  • SELECT @I = 1 SELECT @TX_CNT = #TEMP1.planned_tx_cnt WHILE (@I
  • 这是可行的,您可以使用LOOPCURSOR 甚至recursive CTE。但是我无法理解的是,为什么planned_tx_dt 的日期部分在接下来的几个月中会有所不同。您如何确定 2/15、3/15、4/12、5/10 而不是 2/15、3/15、4/15、5/15?
  • 这是使用数字或计数表的地方。这里根本不需要循环。

标签: sql sql-server loops sql-insert


【解决方案1】:

确保您阅读了我发布的链接。同时,这是一个使用您发布的信息的功能示例。实际上,我在我的系统中拥有该 cteTally 作为视图,因此我不必重新创建它。您可以根据需要调整 cte 部分,以确保有足够的行数。

if OBJECT_ID('tempdb..#temp1') is not null
    drop table #temp1

create table #temp1
(
    patient varchar(50)
    , next_tx_dt date
    , planned_tx_cnt int
    , min_days_bt int
    , start_range date
    , end_range date    
)

insert #temp1
select 'PATIENT_1', '2/15/2015', '4', '28', '2/1/2015', '6/1/2015' union all
select 'PATIENT_2', '2/05/2015', '9', '12', '2/1/2015', '6/1/2015' union all
select 'PATIENT_3', '5/17/2015', '1', '112', '2/1/2015', '6/1/2015';

WITH
    E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
    E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
    E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
    cteTally(N) AS 
    (
        SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
    )

select *, DATEADD(DAY, (N - 1) * min_days_bt, next_tx_dt)
from #temp1 t1
join cteTally t on t.N <= t1.planned_tx_cnt
--where t1.patient = 'PATIENT_1'

【讨论】:

  • 谢谢你,你的例子实际上帮助我更好地理解了这篇文章——对我来说是全新的领域!
  • 如果您阅读了那篇文章并理解了它所说的内容,然后理解了这段代码,它将改变您查看数据的方式。很高兴我的例子有所帮助。
猜你喜欢
  • 1970-01-01
  • 2019-06-07
  • 1970-01-01
  • 1970-01-01
  • 2014-11-26
  • 1970-01-01
  • 2022-01-07
  • 2016-02-15
相关资源
最近更新 更多