0

現在コードで行っていることを、代わりにT-SQLで行うことが可能で、より効率的かどうか疑問に思っています。

コースのデータベースがあります。各コースには、さまざまな場所やさまざまな賞でのコースのバリエーションであるさまざまなオファリングを含めることができます。

これが私の(簡略化された)データベース構造といくつかのサンプルデータです:

CREATE TABLE tblCourse (CourseId int, CourseName varchar(50))
CREATE TABLE tblOffering (OfferingId int, CourseId int, LocationId int, AwardId int)
CREATE TABLE tblLocation (LocationId int, LocationName varchar(50))
CREATE TABLE tblAward (AwardId int, AwardName varchar(50))

INSERT INTO tblCourse VALUES (1, 'Course A')
INSERT INTO tblCourse VALUES (2, 'Course B')

INSERT INTO tblOffering VALUES (1, 1, 1, 1)
INSERT INTO tblOffering VALUES (2, 1, 2, 1)
INSERT INTO tblOffering VALUES (3, 1, 3, 1)
INSERT INTO tblOffering VALUES (4, 1, 1, 2)
INSERT INTO tblOffering VALUES (5, 2, 3, 1)

INSERT INTO tblLocation VALUES (1, 'Location A')
INSERT INTO tblLocation VALUES (2, 'Location B')
INSERT INTO tblLocation VALUES (3, 'Location C')

INSERT INTO tblAward VALUES (1, 'Award A')
INSERT INTO tblAward VALUES (2, 'Award B')

SQLから取得したいのは、コースと賞の組み合わせごとに1つの行です。各行には、場所ごと、およびそのCourseId/AwardIdの組み合わせのコースが利用可能かどうかの列があります。これで、オファリングのないコース/アワードの組み合わせの行が表示されます。

サンプルデータからの必要な結果は、次のようなレコードセットになります。

CourseId | CourseName | AwardId | AwardName | LocationA | LocationB | LocationC
---------+------------+---------+-----------+-----------+-----------+----------
1        | Course A   | 1       | Award A   | True      | True      | True
1        | Course A   | 2       | Award B   | True      | NULL      | NULL
2        | Course B   | 1       | Award A   | NULL      | NULL      | True

(NULLはFalseの場合もあります)

現在、さまざまなJOINSを使用して単純なSELECTステートメントを実行しており、コースと賞の組み合わせごとに複数の行が表示されます。次に、コード内のすべての行をループして、必要な結果を作成します。ただし、結果をページングする必要があるため、これはそれほど効率的ではないと思います。

一時テーブルと一連の個別のクエリを作成することで、ストアドプロシージャでこれをかなり簡単に行うことができると思いますが、それはあまり効率的ではないと思います。T-SQLでそれを行うためのより良い方法があるかどうか疑問に思いますか?

したがって、明確にするために、私が探しているのは、上記のサンプルレコードセットを生成し、ページングを適応させることができるT-SQLクエリまたはストアドプロシージャです。

NB。SQLServer2008を使用しています

4

3 に答える 3

4

動的列の場合:

DECLARE  @COLUMNS VARCHAR(max)
        ,@query varchar(1024)
        ,@True varchar(6)


SELECT @COLUMNS = 
COALESCE(
@Columns + ',[' + L.LocationName + ']',
'[' + L.LocationName +']'
)
FROM tblLocation L

SELECT @True = '''True'''

SELECT @QUERY = 'SELECT C.CourseName
                 ,A.AwardName
                 , pvt.*
FROM (SELECT O.OfferingID AS OID
            ,O.AwardID AS AID
            ,O.CourseID AS CID
            ,L.LocationName AS LID
       FROM tblOffering O Inner Join tblLocation L on L.LocationID = O.LocationID) AS S
PIVOT
(
    count(oID) For LID IN (' +@COLUMNS+ ')
) As pvt
inner join tblCourse C on C.CourseID = CID
inner join tblAward A on A.AwardID = pvt.AID'

EXEC (@QUERY)
GO
于 2012-08-23T01:49:23.430 に答える
3

これにより、サンプル結果のページ付けされたバージョンが生成されます。

declare @tblCourse as table (CourseId int, CourseName varchar(50)) 
declare @tblOffering as table (OfferingId int, CourseId int, LocationId int, AwardId int) 
declare @tblLocation as table (LocationId int, LocationName varchar(50))
declare @tblAward as table (AwardId int, AwardName varchar(50)) 

INSERT INTO @tblCourse VALUES (1, 'Course A') 
INSERT INTO @tblCourse VALUES (2, 'Course B') 

INSERT INTO @tblOffering VALUES (1, 1, 1, 1) 
INSERT INTO @tblOffering VALUES (2, 1, 2, 1) 
INSERT INTO @tblOffering VALUES (3, 1, 3, 1) 
INSERT INTO @tblOffering VALUES (4, 1, 1, 2) 
INSERT INTO @tblOffering VALUES (5, 2, 3, 1) 

INSERT INTO @tblLocation VALUES (1, 'Location A') 
INSERT INTO @tblLocation VALUES (2, 'Location B') 
INSERT INTO @tblLocation VALUES (3, 'Location C') 

INSERT INTO @tblAward VALUES (1, 'Award A') 
INSERT INTO @tblAward VALUES (2, 'Award B') -- This had id 1 in your example.

-- Set the following parameters to control paging:
declare @PageSize as Int = 5
declare @PageNumber as Int = 1

; with CourseAwardSummary as (
  select distinct C.CourseId, C.CourseName, A.AwardId, A.AwardName,
    case when exists ( select 42 from @tblOffering where CourseId = C.CourseId and AwardId = A.AwardId and LocationId = 1 ) then 'True' end as LocationA,
    case when exists ( select 42 from @tblOffering where CourseId = C.CourseId and AwardId = A.AwardId and LocationId = 2 ) then 'True' end as LocationB,
    case when exists ( select 42 from @tblOffering where CourseId = C.CourseId and AwardId = A.AwardId and LocationId = 3 ) then 'True' end as LocationC
  from @tblCourse as C inner join
    @tblOffering as O on O.CourseId = C.CourseId inner join
    @tblAward as A on A.AwardId = O.AwardId
    ),
  CourseAwardSummaryRows as (
    select *, Row_Number() over ( order by CourseName, AwardName ) as RowNumber
      from CourseAwardSummary
    )
    select CourseId, CourseName, AwardId, AwardName, LocationA, LocationB, LocationC
  from CourseAwardSummaryRows
  where ( @PageNumber - 1 ) * @PageSize + 1 <= RowNumber and RowNumber <= @PageNumber * @PageSize
  order by CourseName, AwardName
于 2012-08-23T01:48:26.973 に答える
1

次のクエリは、オファリングテーブルを結合して集約し、その結果をコーステーブルとアワードテーブルに結合することでこれを行います。

select c.CourseId, c.CourseName, oa.AwardId, oa.AwardName,
       oa.LocationA, oa.LocationB, oa.LocationC
from tblCourse c left outer join
     (select o.CourseId, o.AwardId, a.awardName
             max(case when LocationName = 'Location A' then 'true' end) as LocationA,
             max(case when LocationName = 'Location B' then 'true' end) as LocationB,
             max(case when LocationName = 'Location C' then 'true' end) as LocationC
      from tblOffering o join
           tblLocation l
           on o.LocationId = l.LocationId join
           tblAward a
           on a.awardID = o.AwardId
      group by o.CourseId, o.AwardId, a.awardName
     ) oa
     on oa.CourseId = c.CourseId
于 2012-08-23T01:55:10.757 に答える