SQL Serverクエリトップの選択とグループ化
-
08-07-2019 - |
質問
配偶者テーブル 配偶者ID
SpousePreviousAddressesTable PreviousAddressID 、 SpouseID 、FromDate、AddressTypeID
私が現在持っているのは、テーブル全体の最新のものを更新し、SpouseIDに関係なく最新のものにAddressTypeID = 1を割り当てることです
最新のSpousePreviousAddress.AddressTypeID = 1を割り当てたい SpousePreviousAddressesテーブル内の一意のSpouseIDごとに。
UPDATE spa
SET spa.AddressTypeID = 1
FROM SpousePreviousAddresses AS spa INNER JOIN Spouses ON spa.SpouseID = Spouses.SpouseID,
(SELECT TOP 1 SpousePreviousAddresses.* FROM SpousePreviousAddresses
INNER JOIN Spouses AS s ON SpousePreviousAddresses.SpouseID = s.SpouseID
WHERE SpousePreviousAddresses.CountryID = 181 ORDER BY SpousePreviousAddresses.FromDate DESC) as us
WHERE spa.PreviousAddressID = us.PreviousAddressID
グループを作成する必要があると思いますが、SQLはそれほど熱くありません。ありがとう。
動作しているアップデート
これに対する解決策を以前に見つけたことは間違っていました。以下は私がしようとしている解決策です
WITH result AS
(
SELECT ROW_NUMBER() OVER (PARTITION BY SpouseID ORDER BY FromDate DESC) AS rowNumber, *
FROM SpousePreviousAddresses
WHERE CountryID = 181
)
UPDATE result
SET AddressTypeID = 1
FROM result WHERE rowNumber = 1
解決
SQLServer 2005を使用していると仮定すると(前回の試行で得られたエラーメッセージに基づいて)、おそらくこれを行う最も簡単な方法は、共通テーブル式と組み合わせたROW_NUMBER()関数を使用することです。あなたが探していることをしてください:
WITH result AS
(
SELECT
ROW_NUMBER() OVER (PARTITION BY SpouseID ORDER BY FromDate DESC) as rowNumber,
*
FROM
SpousePreviousAddresses
)
UPDATE SpousePreviousAddresses
SET
AddressTypeID = 2
FROM
SpousePreviousAddresses spa
INNER JOIN result r ON spa.SpouseId = r.SpouseId
WHERE r.rowNumber = 1
AND spa.PreviousAddressID = r.PreviousAddressID
AND spa.CountryID = 181
SQLServer2005では、ROW_NUMBER()関数は最も強力なものの1つです。多くの状況で非常に便利です。それについて学ぶのに費やした時間は何度も返済されます。
CTEは、中間結果を保存するためのある種の一時テーブルが不要になるため、コードを単純化するために使用されます。
結果のクエリは高速で効率的でなければなりません。 CTEのselectでは*を使用しますが、これはすべての列を必要としないため少し過剰ですが、クエリ内で何が起こっているのかを確認したい場合は何が起こっているかを示すのに役立ちます。
他のヒント
これを行う1つの方法は次のとおりです。
UPDATE spa1
SET spa1.AddressTypeID = 1
FROM SpousePreviousAddresses AS spa1
LEFT OUTER JOIN SpousePreviousAddresses AS spa2
ON (spa1.SpouseID = spa2.SpouseID AND spa1.FromDate < spa2.FromDate)
WHERE spa1.CountryID = 181 AND spa2.SpouseID IS NULL;
つまり、同じ配偶者とより新しい(より新しい)日付を持つ行 spa2
が存在しない行 spa1
を更新します。
同じ SpouseID
を持つ他のすべての行(存在する場合)と比較して、最大の日付を持つ SpouseID
の値ごとに正確に1行あります。
結合によって暗黙的なグループ化が行われるため、 GROUP BY
を使用する必要はありません。
更新: OUTER JOIN
の目的を誤解していると思います。結合条件に一致する all の行 spa2
がない場合、 spa2。*
のすべての列がNULLとして返されます。それが外部結合の仕組みです。したがって、 spa2.SpouseID IS NULL
をテストすることにより、 spa1
に一致する行 spa2
がない場合を検索できます。
UPDATE spa SET spa.AddressTypeID = 1
WHERE spa.SpouseID IN (
SELECT DISTINCT s1.SpouseID FROM Spa S1, SpousePreviousAddresses S2
WHERE s1.SpouseID = s2.SpouseID
AND s2.CountryID = 181
AND s1.PreviousAddressId = s2.PreviousAddressId
ORDER BY S2.FromDate DESC)
ちょっと推測してください。