我是SQL Server 2005存储过程的初学者.我似乎无法按需要工作.
我有一个sp,它从一个名为annot的表中获取参数@caseid. @caseid被赋值为列src_caseid的值,并且可以在表annot中具有多个引用(ref_caseid)或none.我想设置一个条件并设置正确的shepardsflag,具体取决于我使用INNER JOIN进行的表格中的列法院.
基本上这是场景:
>表annot – ref_caseid,src_caseid,annotation
>表格案例 – caseid,court
来自ref_caseid = caseid的INNER JOIN的结果集示例如下:
ref_caseid src_caseid annotation court
17334 17338 Refd high court
17600 17338 Foll federal court
18271 17338 Foll federal court
43220 17338 Not Foll supreme court
要设置的条件:
从记录集中,如果联邦法院存在,它应该只采取一排联邦法院.如果没有找到联邦法院,那么它将采取其他案件与其他法院价值观.
为实现这一目标,我设立了一个联邦法院计数器.但似乎SQL只读取最后一行并根据它设置@courtFC值.我已经尝试了顺序,但似乎没有工作.
从上面的示例中,案例17338的最终shepardsflag值应为= 3(Foll),因为它应该仅使用“联邦法院”行,并忽略其余行.
但目前的结果是shepardsflag = 2;这是错的
我希望我能解释清楚.
有人可以帮我解决正确的逻辑吗?我应该创建临时表吗?提前致谢.
脚本:
ALTER PROCEDURE [dbo].[spUpdateShepardsFlags] @caseid int = null AS
begin
declare @Shep int
declare @ref_caseid int
declare @court int
declare @courtFC int
declare @annot int
if @caseid is not null
begin
select @court = b.court, @ref_caseid = a.ref_caseid, @annot = a.annotation
from cba_annot a inner join cbm_case b on a.ref_caseid = b.caseid
where a.src_caseid = @caseid
if @court is not null
begin
if @court = 'MYFC'
set @courtFC = @courtFC + 1
if @court <> 'MYFC'
SET @courtFC = @courtFC + 0
PRINT 'The @courtFC counter : ' + CAST(@courtFC AS CHAR)
end
if @court is not NULL
begin
if @courtfc > 0
begin
if exists(select a.ref_caseid, b.court, a.annotation, a.src_caseid from
cba_annot a inner join cbm_case b on a.ref_caseid = b.caseid)
begin
if exists(select src_caseid from cba_annot where (annotation like '%Refd%'
or annotation like '%Comp%')
and src_caseid = @caseid)
set @Shep = 4
if exists(select src_caseid from cba_annot where (annotation like '%Foll%'
or annotation like '%Aff%')
and src_caseid = @caseid)
set @ShepFC = 3
update cbm_case
set shepardsflag = @shep
where caseid=@caseid
end
end
else -- if @courtFC = 0
begin --new
if exists(select a.ref_caseid, b.court, a.annotation, a.src_caseid from
cba_annot a inner join cbm_case b on a.ref_caseid = b.caseid)
begin
if exists(select src_caseid from cba_annot where (annotation like '%Refd%'
or annotation like '%Comp%')
and src_caseid = @caseid)
set @Shep = 4
if exists(select src_caseid from cba_annot where (annotation like '%Foll%'
or annotation like '%Aff%')
and src_caseid = @caseid)
set @Shep = 3
if exists(select src_caseid from cba_annot where (annotation like '%Not Foll%'
or annotation like '%Dist%')
and src_caseid = @caseid)
set @Shep = 2
update cbm_case
set shepardsflag = @shep
where caseid=@caseid
end
end -- new
end
else --- if court is NULL -- case not referred by any other case
update cbm_case
set shepardsflag = 5
where caseid=@caseid
end
else -- if caseid is null
-- other condition
最佳答案 您对SQL的理解存在一些实际问题,我非常怀疑临时表是否相关.
1)变量初始化为null,但这似乎并没有显着搞砸你. (@courtFC 0不会评估你可能在想的方式.)
2)你做作业的方式取决于顺序,最后一个完全如你所注意到的那样获胜.而不是说:
select @court = b.court, ...
你可以使用这个:
select @courtFC = count(b.court) ... where b.court = 'federal court'
你似乎也试图写一个循环,我认为这是你困惑的另一部分. SQL是关于集合,一次操作多行.
3)内部块中的所有EXISTS子查询都缺少相关caseid上的过滤器.
您的方法实际上可能仅适用于这些更改.
我的版本并不是为了使事情复杂化,但我担心你会遇到麻烦.这是一个基于集合的解决方案,实际上是一种更自然的方式.
if @caseid is not null /* short-circuit the update, but probably not necessary */
update cbm_case
set shepardsflag = coalesce(
(
select
case
max( /* highest precendence wins */
case /* map annotations by precedence i.e. */
/* if there are multiple annotations, */
/* which one takes priority */
when a.annotation in ('Refd', 'Comp') then 'P1'
when a.annotation in ('Foll', 'Aff') then 'P2'
when a.annotation in ('Not Foll', 'Dist') then 'P3'
else cast(0/0 as char(2)) /* error, I think */
end
)
when 'P1' then 4 /* translate back to shepardsflag */
when 'P2' then 3
when 'P3' then 2
end
from
cba_annot as a inner join cbm_case as refcase
on refcase.caseid = a.ref_caseid
where
a.src_caseid = cbm_case.caseid
and (
cbm_case.court <> 'federal court' /* all if src case not federal */
or refcase.court = 'federal court' /* always get federal */
)
),
5
)
where caseid = @caseid;
编辑2
忽略我在3)中的评论.再看看,我认为由于括号和换行符,我误读了OP的代码.
编辑3
修复了第一行中缺少@字符导致的错误.