2012-07-04 132 views
4

我是SQL Server 2005存储过程的初学者。我似乎无法按要求工作。如何根据SQL Server 2005中的条件返回一组值?

我有一个sp从一个名为annot的表中获取参数@caseid。 @caseid被分配到列src_caseid的值,并且可以在表annot中有多个参考(ref_caseid)或没有。我想设置一个条件并根据表case中的列court设置适当的shepardsflag,我使用INNER JOIN。

基本上,这是该方案:

  • annot - ref_caseid, src_caseid, annotation
  • case - caseid, court

组从内的结果的实施例JOIN上ref_caseid = caseid这样的:

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 

需要设置的条件:

从记录集中,如果存在federal court,则只应该执行federal court行。如果发现没有federal court,那么它会将其他案件与其他法院值进行比较。

为了达到这个目的,我为federal court计数设置了一个计数器。但似乎SQL只读取最后一行并基于它设置@courtFC值。我试过order by,但似乎没有工作。

从上面的示例中,case 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 [email protected] 
       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 [email protected] 
       end 

      end -- new 
     end 
    else --- if court is NULL -- case not referred by any other case 
     update cbm_case 
     set shepardsflag = 5 
     where [email protected] 
    end 

else -- if caseid is null 

-- other condition 
+0

你得到了这个答案吗? –

回答

2

你有一些真正的问题与你的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 修正了第一行缺少@字符引起的错误。

+0

thx很多这个。但我已经找到了解决办法TRU临时表: \t \t INSERT INTO #court(ref_caseid,src_caseid,法院,注释) \t \t SELECT ref_caseid,src_caseid,法院,注释 \t \t FROM(SELECT a.ref_caseid,B。场,a.annotation,a.src_caseid,RANK()OVER \t \t \t(PARTITION BY a.src_CaseID ORDER BY CASE WHEN b.court = 'MYFC' THEN ELSE 1 2 END)AS行 \t \t FROM cba_annot一个INNER JOIN cbm_case b ON a.ref_caseid = b.caseid \t \t WHERE a.src_caseid = 17338)派生的WHERE行= 1 – user1500714

+0

您的示例数据显示可以有多个联邦法院参考案例,因此您*将*具有RANK()中的关系,因此ROW = 1的多行。我猜你使用该临时表作为您的逻辑来确定是否存在'MYFC'行并且您只关心法院专栏。所以看起来你已经使用了一个临时表和RANK函数,你真的可以在你的case表达式中首先完成一个ORDER BY。而且你仍然使用十多个SELECT和UPDATE,你可以通过采用我提出的方法来使用它。 – shawnt00

+0

嗨,我尝试了一下你的建议,但是在最后一行';'给出了语法错误。 我尝试了几个更改,但仍然抛出语法错误。有人可以协助吗? 非常感谢。 – user1500714

相关问题