-2

同じ行の期間ごとにユーザー数 (ScheduleID) を表示するビューを変更する必要があります。これで、Period テーブルの内容が大きくなり、3 つ以上の期間を含めることができます。

実際の SQL は次のとおりです。

SELECT r.Code,
 SUM(CASE WHEN s.PeriodID=1 THEN 1 ELSE 0 END) AS PeriodID1,
 SUM(CASE WHEN s.PeriodID=2 THEN 1 ELSE 0 END) AS PeriodID2,
 SUM(CASE WHEN s.PeriodID=3 THEN 1 ELSE 0 END) AS PeriodID3,
 SUM(CASE WHEN s.PeriodID IN (1,2,3) THEN 1 ELSE 0 END) AS Total
 FROM Schedules s
 JOIN Periods p ON p.PeriodID = s.PeriodID
 JOIN Resources r ON r.ResourceID = s.ResourceID
 GROUP BY r.Code;

サンプル データ: テーブル スケジュール

ScheduleID(int) ResourceID(int) ResourceCode(varchar 4) PeriodID(int)
1               1               AA                      1
2               1               AA                      3
3               1               AA                      3
4               2               BB                      1
5               3               CC                      1
6               1               AA                      1
7               3               CC                      2
8               3               CC                      3
9               2               BB                      1
10              2               BB                      2
11              2               BB                      3
12              1               AA                      3

テーブル期間

PeriodID(int) Code (varchar 4)
1             P1 
2             P2
3             P3
4             P4  
5             P5
6             P6
7             P7
8             P8

私が必要とする結果は次のとおりです。

ResourceCode PeriodID1 PeriodID2 PeriodID3 ... PeriodID8  TOTAL
AA           2         0         3             0          5
BB           2         1         1             0          4
CC           1         1         1             0          3

Periods テーブルの内容が動的になりました。

データベースのバージョンは Microsoft SQL 2008 です

ストアドプロシージャを作成せずにそれを行うことが可能かどうかを知りたい...そしてこれを次のような1つのクエリで行う:

SELECT *
FROM (
SELECT R.Code, P.PeriodID, COUNT(S.ScheduleID) AS RPCount
FROM Schedules S INNER JOIN Periods P ON S.PeriodID = P.PeriodID
JOIN Resources R ON S.ResourceID = R.ResourceID
WHERE S.ResourceID is not null
GROUP BY R.Code, P.PeriodID
) as data
PIVOT
(
    SUM(RPCount)
    --FOR PeriodID IN ([1],[2],[3])
    FOR PeriodID IN (SELECT PeriodID From Periods)
)AS pvt
ORDER BY Code
4

3 に答える 3

4

SQL Server を使用しているため、PIVOT 関数を実装できます。ピリオド値の数が不明な場合は、動的 SQL を使用する必要があります。

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT distinct ',' + QUOTENAME('PeriodId'+cast(periodid as varchar(10))) 
                    from Periods
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT resourcecode, ' + @cols + ' , Total
            from 
            (
               select s.resourcecode, 
                 ''PeriodId''+cast(p.periodid as varchar(10)) period,
                count(*) over(partition by s.resourcecode) Total
               from periods p
               left join schedules s
                 on p.periodid = s.periodid
            ) x
            pivot 
            (
                count(period)
                for period in (' + @cols + ')
            ) p 
            where resourcecode is not null
            order by resourcecode'

execute(@query)

SQL Fiddle with Demoを参照してください。これにより、次の結果が得られます。

| RESOURCECODE | PERIODID1 | PERIODID2 | PERIODID3 | PERIODID4 | PERIODID5 | PERIODID6 | PERIODID7 | PERIODID8 | TOTAL |
------------------------------------------------------------------------------------------------------------------------
|           AA |         2 |         0 |         3 |         0 |         0 |         0 |         0 |         0 |     5 |
|           BB |         2 |         1 |         1 |         0 |         0 |         0 |         0 |         0 |     4 |
|           CC |         1 |         1 |         1 |         0 |         0 |         0 |         0 |         0 |     3 |

MySQL でタグ付けされた以前の質問に基づいて、MySQL をデータベースとして使用していると想定しています。その場合、PIVOT 関数がないため、集計関数と CASE 式を使用して、データの行を列に変換する必要があります。

列の値がわかっている場合は、クエリをハードコーディングできます。

select resourcecode,
  sum(case when period = 'PeriodId1' then 1 else 0 end) PeriodId1,
  sum(case when period = 'PeriodId2' then 1 else 0 end) PeriodId2,
  sum(case when period = 'PeriodId3' then 1 else 0 end) PeriodId3,
  sum(case when period = 'PeriodId4' then 1 else 0 end) PeriodId4,
  sum(case when period = 'PeriodId5' then 1 else 0 end) PeriodId5,
  sum(case when period = 'PeriodId6' then 1 else 0 end) PeriodId6,
  sum(case when period = 'PeriodId7' then 1 else 0 end) PeriodId7,
  sum(case when period = 'PeriodId8' then 1 else 0 end) PeriodId8,
  count(*) Total
from
(
  select concat('PeriodId', p.periodid) Period,
    s.resourcecode
  from periods p
  left join schedules s
    on p.periodid = s.periodid
) d
where resourcecode is not null
group by resourcecode;

SQL Fiddle with Demoを参照してください。ただし、値が不明または動的である場合は、準備済みステートメントを使用して、実行する SQL 文字列を生成する必要があります。

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'sum(CASE WHEN period = ''',
      concat('PeriodId', periodid),
      ''' THEN 1 else 0 END) AS `',
      concat('PeriodId', periodid), '`'
    )
  ) INTO @sql
FROM periods;

SET @sql 
  = CONCAT('SELECT resourcecode, ', @sql, ' , count(*) Total
            from
            (
              select concat(''PeriodId'', p.periodid) Period,
                s.resourcecode
              from periods p
              left join schedules s
                on p.periodid = s.periodid
            ) d
            where resourcecode is not null
            group by resourcecode');


PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SQL Fiddle with Demoを参照してください。

于 2013-07-12T12:13:38.227 に答える
0

ピボットを使用する

これを試して

SELECT *
    FROM (
        SELECT 
           S.ResourceCode ,
           P.PeriodID  AS period,
          COUNT(*) AS PCount
        FROM Schedules S INNER JOIN Periods P ON S.PeriodID =P.PeriodID 
        GROUP BY S.ResourceCode ,P.PeriodID
    ) as s
    PIVOT
    (

        PCount,
        FOR [period] IN (SELECT DISTINCT PeriodID From Periods)
    )AS pivot
于 2013-07-12T10:18:53.807 に答える
0

MS Sql サーバーの以下のコードを試してください:

DECLARE @column VARCHAR(MAX), @SumQuery VARCHAR(MAX)

SELECT 
    @column = COALESCE(@column + '], [', '')+ CAST(PeriodID as nvarchar(10)),
    @SumQuery = COALESCE(@SumQuery + ']+[', '')+ CAST(PeriodID as nvarchar(10))
FROM 
    Periods 
GROUP BY PeriodID

EXEC ('select *, ['+@SumQuery+'] as [Total] From
(
    select * From Schedules
)up
pivot (count(ScheduleID) for PeriodID in (['+@column+'])) as pvt')
于 2013-07-12T11:46:22.320 に答える