4

私は SQL Server 2005 ストアド プロシージャの初心者です。思うように動かせないようです。

というテーブルからパラメーター @caseid を受け取る sp がありますannot@caseidは列の値に割り当てられ、src_caseid複数の参照 ( ref_caseid) を持つことも、テーブル内に何も持たないこともできますannot。INNER JOINを使用して行ったcourtテーブルの列に応じて、条件を設定し、適切なshepardsflagを設定したいと思います。case

基本的にこれはシナリオです:

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

次のようなINNER 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たが、うまく機能していないようです。

上記のサンプルから、ケース 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
4

1 に答える 1

2

あなたは SQL の理解にいくつかの本当の問題を抱えており、一時テーブルが適切であるかどうかを真剣に疑っています。

1)変数は null として初期化されますが、それによって大幅に混乱することはないようです。(@courtFC + 0 は、おそらくあなたが考えていた方法であなたを評価しません。)

2)割り当てを行う方法は順序に依存し、最後のものはあなたが気づいたとおりに勝ちます。言う代わりに:

select @court = b.court, ...

あなたはこれを使うことができました:

select @courtFC = count(b.court) ... where b.court = 'federal court'

また、ループを記述しようとしているようにも見えますが、それはあなたの混乱の別の部分だと思います。SQL はセットに関するものであり、一度に複数の行を操作します。

3)内部ブロック内のすべての EXISTS サブクエリに、関連するケース ID のフィルターがありません。

あなたのアプローチは、実際にはこれらの変更だけでうまくいくかもしれません。

ここでの私のバージョンは、物事を複雑にすることを意図したものではありませんが、問題が発生するのではないかと心配しています. これは、より自然な方法であるセットベースのソリューションです。

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 最初の行に @ 文字がないために発生したエラーを修正しました。

于 2012-07-08T04:41:44.597 に答える