以下は、特定の状況に適したアプローチである場合とそうでない場合がありますが、自由に使用できる便利な手法になる可能性があります。
select ステートメントにコードを追加して、これらの「下流」のような質問に答えることができます (追加された基準または SSRS を介して)。SQL Fiddle のこの変更を参照してください。
select pid, firstName, lastName, dateOfBirth, obsName, obsValue, obsDate,
rowRank, CASE rowRank WHEN 1 THEN 1 ELSE 0 END AS countableRow
from
(
select Person.pid, Person.firstName, Person.lastName, Person.dateOfBirth
, Obs.obsName, Obs.obsValue, Obs.obsDate,
ROW_NUMBER() OVER (PARTITION BY Person.pid, Person.firstName, Person.lastName, Person.dateOfBirth ORDER BY Obs.obsDate) AS rowRank
from Person
join Obs on Person.pId = Obs.pId
) rankedData
このrowRank
フィールドは、グループに相対的なランキング番号を作成します。これは、下流で役立つ場合とそうでない場合があります。countableRow
フィールドは 1 または 0 のいずれかになり、各グループには 1 を含む行が 1 つだけ含まれます。これを行うSUM(countableRow)
と、データ内の適切な数のグループが得られます。
これで、各グループの最初の行で 1 のような定数スカラーの代わりに実際のフィールド値をダンプすることで、(必要に応じて) この機能を拡張できます。したがって、CASE rowRank WHEN 1 THEN dateOfBirth ELSE NULL END AS countableDOB
たとえば、このデータセットだけを使用して、誕生日ごとに異なる人の総数を取得できます。
もちろん、とにかく @Russell のようなメソッドを SQL で使用してこれらすべてのことを実行できるため、これは状況に一致しない可能性がある特定のダウンストリーム要件に最も関連します。
編集
明らかに、 countableRow フィールドには、必要なクエリの種類に対する万能のソリューションはありません。別の SQL FiddlePARTITION BY
に戦略の例をいくつか追加しました。
select pid, firstName, lastName, dateOfBirth, obsName, obsValue, obsDate,
rowRank, CASE rowRank WHEN 1 THEN 1 ELSE 0 END AS countableRow,
valueRank, CASE valueRank WHEN 1 THEN 1 ELSE 0 END AS valueCount,
dobRank, CASE WHEN dobRank = 1 AND dateOfBirth IS NOT NULL THEN 1 ELSE 0 END AS dobCount
from
(
select Person.pid, Person.firstName, Person.lastName, Person.dateOfBirth
, Obs.obsName, Obs.obsValue, Obs.obsDate,
ROW_NUMBER() OVER (PARTITION BY Person.pid, Person.firstName, Person.lastName, Person.dateOfBirth ORDER BY Obs.obsDate) AS rowRank,
ROW_NUMBER() OVER (PARTITION BY Obs.obsName, Obs.obsValue ORDER BY Obs.obsDate) AS valueRank,
ROW_Number() OVER (PARTITION BY Person.dateOfBirth ORDER BY Person.pid) AS dobRank
from Person
join Obs on Person.pId = Obs.pId
) rankedData
これが常に適切であると示唆していると誰かが誤解しないように、明らかにそうではありません。これは、追加の SQL クエリを使用して特定の回答を得るための優れたソリューションではありません。これにより、消費するコード内のそのような質問にすべて 1 つの結果セットで簡単に答えることができるように、十分な情報をエンコードすることができます。それが便利になるところです。
2回目の編集
レースデータを複数の場所に保存している場合、これができるかどうか疑問に思っていたので、答えは絶対です。以前の SQL Fiddle からコードを修正しました。これは新しいもので利用できるようになりました。
select pid, firstName, lastName, dateOfBirth, obsName, obsValue, obsDate,
rowRank, CASE rowRank WHEN 1 THEN 1 ELSE 0 END AS countableRow,
valueRank, CASE valueRank WHEN 1 THEN 1 ELSE 0 END AS valueCount,
dobRank, CASE WHEN dobRank = 1 AND dateOfBirth IS NOT NULL THEN 1 ELSE 0 END AS dobCount,
raceRank, CASE WHEN raceRank = 1 AND (race IS NOT NULL OR obsName = 'RACE') THEN 1 ELSE 0 END AS raceCount
from
(
select Person.pid, Person.firstName, Person.lastName, Person.dateOfBirth, Person.[race]
, Obs.obsName, Obs.obsValue, Obs.obsDate,
ROW_NUMBER() OVER (PARTITION BY Person.pid, Person.firstName, Person.lastName, Person.dateOfBirth ORDER BY Obs.obsDate) AS rowRank,
ROW_NUMBER() OVER (PARTITION BY Obs.obsName, Obs.obsValue ORDER BY Obs.obsDate) AS valueRank,
ROW_NUMBER() OVER (PARTITION BY Person.dateOfBirth ORDER BY Person.pid) AS dobRank,
ROW_NUMBER() OVER (PARTITION BY ISNULL(Person.race, CASE Obs.obsName WHEN 'RACE' THEN Obs.obsValue ELSE NULL END) ORDER BY Person.pid) AS raceRank
from Person
left join Obs on Person.pId = Obs.pId
) rankedData
ご覧のとおり、新しい Fiddle では、Race の数が 3 として適切にカウントされます。2 つは Obs テーブルにあり、3 番目は Person テーブルにあります。秘訣は、PARTITION BY
生の列出力だけでなく、式を含めることができることです。ここで結合を左結合に変更したこと、および CASE を使用して obsValue WHERE obsName is 'RACE' のみを含める必要があることに注意してください。少し複雑ですが、それほど複雑ではなく、かなり複雑なケースでも適切に処理します。