1

2 つのシステム間の統合に取り組んでいます。私のコース システムには、スタッフ メンバーである必要があるインストラクターへの参照があります。問題は、コース システムではインストラクター レコードをローカルで作成できることです (スタッフ システムからコース システムにフィードするジョブが既にあります)。

コースには複数のインストラクターがいる場合があり、ビジネス上の理由から、ローカルのインストラクター レコードがプレースホルダーとして作成されることがあります。すべての「実際の」インストラクターを 1 つの文字列に連結する必要がありますが、コースに設定されているインストラクターのいずれかが「実際の」インストラクターでない場合は、空の文字列を出力する必要があります。また、インストラクターが割り当てられていないコースを作成することもできます。

コースシステム

Courses instructorID InstructorName  InstructorOrder
-----------------------------------------------------
ach01   1            Smith           1
ach01   2            Brown           2
phy01   3            James           1
sci01   1            Smith           1
sci01   4            Doe             2
acc01   NULL         NULL            NULL

スタッフ制度

ID   LastName
--------------
1    Smith
2    Brown
3    James

出力

Course  Instructors
-------------------------
arc01   'Smith, Brown'
phy01   'James'
sci01   ''
acc01   ''

これは私が思いついたSQLですが、同じ結果を得るためのより良い方法があるかどうか知りたいです

select courseID,
       isnull(case max(case when x.rn = 1 then isnull(lastname, '-|-') else '' end) when '-|-' then NULL else max(case when x.rn = 1 then lastname else '' end) end +
              case max(case when x.rn = 2 then isnull(lastname, '-|-') else '' end) when '-|-' then NULL else max(case when x.rn = 2 then ', ' + lastname else '' end) end +
              case max(case when x.rn = 3 then isnull(lastname, '-|-') else '' end) when '-|-' then NULL else max(case when x.rn = 3 then ', ' + lastname else '' end) end +
              case max(case when x.rn = 4 then isnull(lastname, '-|-') else '' end) when '-|-' then NULL else max(case when x.rn = 4 then ', ' + lastname else '' end) end
              , '') Instructors
from (select courseID, s.lastname,
             ROW_NUMBER() over(partition by courseID order by InstructorOrder) rn
      from Courses c left join  
           Active_Staff s on c.instructorID = s.ID 
      ) x
group by courseID
4

2 に答える 2

2

これは少し異なる構文を使用しますが、クエリは基本的に、既存のクエリとまったく同じように動作します。パフォーマンスの違いはまったくないと思います。

select P.Courses,
       case when S.Instructors like '%NOSTAFF%' then '' else S.Instructors end as Instructors
from (
     select C.Courses,
            isnull(S.LastName, 'NOSTAFF') as LastName,
            row_number() over(partition by C.Courses order by C.InstructorOrder) as rn
     from Courses as C
       left outer join Staff as S
         on C.instructorID = S.ID
     ) as T
pivot (
      max(T.LastName) for T.rn in ([1],[2],[3],[4])
      ) as P
cross apply
      (
      select isnull(P.[1], '')+isnull(P.[2], '')+isnull(P.[3], '')+isnull(P.[4], '') as Instructors
      ) as S
于 2013-03-27T17:06:10.127 に答える
1

これは少し複雑に見えます (そして、おそらくそうです) が、仕事は完了します:

;WITH CTE1 AS 
(
    SELECT * FROM Courses c
    LEFT JOIN dbo.Active_Staff s ON c.instructorID = s.ID
)
,CTE2 AS
(  
    SELECT  CourseID, 
        STUFF((SELECT ', ' + LastName 
              FROM   CTE1 c2 
              WHERE  c2.CourseID = c1.CourseID 
              ORDER BY c2.InstructorOrder
              FOR XML PATH('')), 1, 2, '')  LastNames
    FROM  CTE1 c1 
    GROUP BY CourseID
)
SELECT
    CourseID,
    CASE WHEN EXISTS (SELECT * FROM CTE1  WHERE LastName IS NULL AND CTE1.CourseID = Cte2.CourseID) THEN '' ELSE LastNames END AS Instructors
FROM CTE2 

基本的に、最初に連結されたすべての文字列を取得します。STUFF と FOR XML PATH の組み合わせを使用してから、少なくとも 1 つの「ダミー」インストラクターがいる文字列を空の文字列に置き換えます。

これがSQL Fiddleのデモです

于 2013-03-27T17:10:07.373 に答える