0

ROW_NUMBER()現在の行と比較した前の行に基づいて位置の変化を計算しようとしていますROW_NUMBER()

私のクエリは、 ROW_NUMBER() OVER .. 句で再帰的な cte を使用しています。これにより、年ごとに結果の行番号がきちんと得られます。

WITH positions AS (
    SELECT 
        [incidents].state_id, [incidents].year_id, MAX(number_of_incidents) AS total_incidents_in_year,
        ROW_NUMBER() OVER(PARTITION BY [incidents].year_id ORDER BY MAX(number_of_incidents) DESC) AS position
    FROM
        [incidents]
    INNER JOIN
        years AS dy ON dy.year_id = [incidents].year_id
    INNER JOIN
        states AS ds on ds.state_id = [incidents].state_id
    GROUP BY
        [incidents].state_id, [incidents].year_id
)

この後、クエリは位置を比較して行番号間の変化を計算します。

SELECT
    ds.state_name, ds.state_id, [before].total_incidents_in_year, dy.year,
    [before].position AS before_position, [after].position AS after_position,
    ([before].position - [after].position) AS change
FROM
    positions AS [before]
LEFT JOIN 
    positions AS [after] ON [before].position = [after].position + 1 AND [before].state_id = [after].state_id AND [before].year_id = [after].year_id
INNER JOIN
    years AS dy ON dy.year_id = [before].year_id
INNER JOIN
    states AS ds on ds.state_id = [before].state_id
ORDER BY
    [before].year_id ASC, [before].total_incidents_in_year DESC

残念ながら、[after] 位置は常に null であるため、これは機能しません。

これは説明が少し難しいので、sqlfiddle リンクを含めました: http://www.sqlfiddle.com/#!18/c7e57e/1

--

この画像は、私が達成しようとしていることを視覚的に説明しています 私の想定アウトプット

2011 年にミネソタは 1 位、2012 年にミネソタは 3 位、変化は +2

2011 年のアイオワは 6 位、2012 年のアイオワは 4 位で、変化は -2 です。

2011 年のサウスダコタ州は 5 位、2012 年のサウスダコタ州は 5 位で、変化は 0 です

ありがとうございました

4

1 に答える 1

1

理解した。

ROW_NUMBER() で誤って結合しようとしていたため、結合の不一致が発生しました。これは、行番号が状態 ID と正しく一致するとは限らないためです。

year年ごとの変化を計算する正しい方法であるに参加するように変更した後、すべてがまとまりました。

WITH positions AS (
    SELECT 
        [incidents].state_id, dy.year, MAX(number_of_incidents) AS total_incidents_in_year,
        ROW_NUMBER() OVER(PARTITION BY dy.year ORDER BY MAX(number_of_incidents) DESC) AS position
    FROM
        [incidents]
    INNER JOIN
        years AS dy ON dy.year_id = [incidents].year_id
    INNER JOIN
        states AS ds on ds.state_id = [incidents].state_id
    GROUP BY
        [incidents].state_id, dy.year
)
SELECT
    ds.state_name, ds.state_id, [before].total_incidents_in_year, dy.year,
    [before].position AS before_position,
    ([before].position - [after].position) AS change
FROM
    positions AS [before]
LEFT JOIN 
    positions AS [after] ON [before].state_id = [after].state_id AND [before].year = [after].year + 1
INNER JOIN
    years AS dy ON dy.year = [before].year
INNER JOIN
    states AS ds on ds.state_id = [before].state_id
ORDER BY
    [before].year ASC, [before].total_incidents_in_year DESC

http://www.sqlfiddle.com/#!18/c7e57e/11

于 2019-04-25T09:29:34.783 に答える