クロスタブ-同じ列に異なる日付(会議1、会議2、会議3など)を保存する

StackOverflow https://stackoverflow.com/questions/1434717

  •  07-07-2019
  •  | 
  •  

質問

異なる日付を追跡する必要があります(動的)。そのため、特定のタスクについて、X個の日付を追跡することができます(たとえば、DDR1会議日、DDR2会議日、期日など)。

私の戦略は、各日付の説明を保存する1つのテーブル(DateTypeID、DateDescription)を作成することでした。次に、メインテーブル(ID、TaskDescription、DateTypeID)を作成できます。したがって、すべての日付は1つの列に含まれ、TypeIDを調べることでその日付が何を表すかを知ることができます。問題は、グリッドに表示することです。クロス集計クエリを使用する必要があることは知っていますが、動作させることはできません。たとえば、SQL Server 2000でCaseステートメントを使用して、各列名が日付型の名前になるようにテーブルをピボットします。次の表がある場合:

DateTypeテーブル

DateTypeID |日付の説明

 1           | DDR1
 2           | DDR2
 3           | DueDate


タスクテーブル

ID | TaskDescription

1 | Create Design
2 | Submit Paperwork


Tasks_DateTypeテーブル

TasksID | DateTypeID |日付

1       |     1         | 09/09/2009
1       |     2         | 10/10/2009
2       |     1         | 11/11/2009
2       |     3         | 12/12/2009


結果は次のようになります。

TaskDescription | DDr1 | DDR2 | DueDate

Create Design     |09/09/2009 | 10/10/2009 | null
Submit Paperwork  |11/11/2009 | null       | 12/12/2009

誰も私がこれを研究する方法を知っているなら、感謝しています。日付ごとに列を作成する代わりにこれを行う理由は、ユーザーがテーブルに列を手動で追加してhtmlコードを編集することなく、将来ユーザーが必要なだけ日付を追加できるようにするためです。これにより、日付を比較したり、タイプ別に今後のタスクを表示したりするための簡単なコードも可能になります(例:「デザインのDDR1日付の作成」が近づいています)。

役に立ちましたか?

解決

これはあなたのデータでテストされた適切な答えです。最初の2つの日付タイプのみを使用しましたが、とにかくこれをすぐに作成します。

Select 
    Tasks.TaskDescription,     
    Min(Case DateType.DateDescription When 'DDR1' Then Tasks_DateType.Date End) As DDR1,     
    Min(Case DateType.DateDescription When 'DDR2' Then Tasks_DateType.Date End) As DDR2
From
    Tasks_DateType
    INNER JOIN Tasks ON Tasks_DateType.TaskID = Tasks.TaskID
    INNER JOIN DateType ON Tasks_DateType.DateTypeID = DateType.DateTypeID
Group By
    Tasks.TaskDescription

編集

vanは、日付のないタスクは表示されないことに言及しました。これは正しいです。左結合(再び、vanが言及)を使用してクエリを少し再構築すると、現時点では必要ではありませんが、すべてのタスクが返されます。

Select 
    Tasks.TaskDescription,     
    Min(Case DateType.DateDescription When 'DDR1' Then Tasks_DateType.Date End) As DDR1,     
    Min(Case DateType.DateDescription When 'DDR2' Then Tasks_DateType.Date End) As DDR2
From
    Tasks   
    LEFT OUTER JOIN Tasks_DateType ON Tasks_DateType.TaskID = Tasks.TaskID
    LEFT OUTER  JOIN DateType ON Tasks_DateType.DateTypeID = DateType.DateTypeID
Group By
    Tasks.TaskDescription

他のヒント

ピボットされた列が不明(動的)の場合、ms-sql 2000または2005のいずれかで手動でクエリを作成する必要があります。つまり、PIVOTなしで実行します。

これには、ストアドプロシージャ(通常はno-no)で動的SQLを実行するか、動的SQLでビューをクエリすることが含まれます。後者は私が一般的に行っているアプローチです。

ピボットについては、ここで説明するように、caseステートメントよりもRozenshteinメソッドの方が好きです。

http://www.stephenforte.net /PermaLink.aspx?guid=2b0532fc-4318-4ac0-a405-15d6d813eeb8

編集

linq-to-sqlでもこれを行うことができますが、かなり非効率的なコードを出力します(少なくともlinqpadで表示する場合)ので、お勧めしません。まだ興味があれば、その方法の例を投稿できます。

ピボット演算子の個人的な経験はありませんが、より良い解決策を提供できます。

しかし、私は過去にcase文を使用しました

SELECT 
    TaskDescription, 
    CASE(DateTypeID = 1, Tasks_DateType.Date) AS DDr1, 
    CASE(DateTypeID = 2, Tasks_DateType.Date) AS DDr2,
    ...
FROM Tasks 
    INNER JOIN Tasks_DateType  ON Tasks.ID = Tasks_DateType.TasksID
    INNER JOIN DateType ON Tasks_DateType.DateTypeID = DateType.DateTypeID
GROUP BY TaskDescription

これは機能しますが、タスクの説明が追加されるたびにSQLを変更する必要があるため、理想的ではありません。

編集:

PIVOTキーワードがSqlServer 2005に追加されたように見えます。この例は、 2000&の両方でピボットクエリを実行する2005、しかし、それは私の答えに似ています。

バージョン-1: + simple、-DateTypeが追加されるたびに変更する必要があります。したがって、動的なソリューションには適していません。

SELECT      tt.ID,
            tt.TaskDescription,
            td1.Date AS DDR1,
            td2.Date AS DDR2,
            td3.Date AS DueDate
FROM        Tasks tt
LEFT JOIN   Tasks_DateType td1
        ON  td1.TasksID = tt.ID AND td1.DateTypeID = 1
LEFT JOIN   Tasks_DateType td2
        ON  td2.TasksID = tt.ID AND td2.DateTypeID = 2
LEFT JOIN   Tasks_DateType td3
        ON  td3.TasksID = tt.ID AND td3.DateTypeID = 3

バージョン2 :完全に動的です(いくつかの制限はありますが、処理できます-Googleで検索してください):

動的なピボットクエリの作成。 ダイナミッククロスタブ/ピボットテーブルを参照してください。 UDFのSPを1つ作成し、それを複数の目的に使用できます。これは元の投稿であり、多くのリンクと改善点を見つけることができます。

バージョン3 クライアントコードが処理できるようにそのままにしておきます。動的なデータセットを返すようにSQLを設計するのではなく、クライアント(プレゼンテーションレイヤー)で処理します。クエリの結果として生じる動的な列を処理したくないので、正確にそれを推測する必要があります。 バージョン2 を使用する唯一の理由は、結果がレポートのテーブルとして直接表示される場合です。 真に動的なデータの他のすべてのケースでは、クライアントコードを使用します。たとえば、構造があり、フィールドDueDateが必須であるというロジックをどのように添付しますか。DB制約は使用できません。 DDR1がDDR2よりも高くないことをどのように確認しますか?これらがデータベース(CONSTRAINTSを使用できる場所)内の別個の(静的)列でない場合、クライアントコードはデータの整合性を検証します。

がんばって!

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top