2011-07-18 3 views
2

共通テーブル式を使用した簡単な自動インクリメントに問題があります。 (私は私の増分のための条件を使用しているので、私はROW_NUMBER()を望んでいないのでここでは動作しない私の問題の単純化バージョンです。私は次のことをしようとすると、「無効な列名を 『N』」::私はこのエラーを取得するCTEをオートインクリメントに使用するT-SQL

WITH NumberSongPair (n,s) AS (
    SELECT 0 as n,SongKey as s from Songs where SongKey = 1 
    UNION ALL 
    SELECT 1 + n as n,SongKey as s 
    from Songs 
    WHERE n < 500) 
SELECT n,s FROM NumberSongPair 
OPTION (MAXRECURSION 500) 

なぜそれが新たに作成されたインクリメント列として「N」を認識できないのですか?テーブルから列を選択するときに数字を増やすことができれば、最初の選択をすべて一緒に取り除くだけで幸せになれます。

あなたは私の全体的な目標について興味があれば、それは曲をランク付けします....このような何かを持つ条件付き:

WITH Nbrs (base, n,ctr) AS (
    SELECT 0,0,0 UNION ALL 
    SELECT 1 + base,'n' = case 
         when (base + 1)%2=0 then ctr 
         when ctr <=20 then ctr 
         else null end, 
       'ctr' = case 
         when (base + 1)%2=0 then ctr + 1 
         else ctr end 
    FROM Nbrs WHERE base < 500) 
SELECT n FROM Nbrs 
OPTION (MAXRECURSION 500) 

EDIT ...

申し訳ありませんが、私の説明は「wasn非常に良い。私はちょうど増分の代わりにヌルになる別の擬似自己増分列を追加したかっただけです。

declare @songs table (songkey int, dropable bit, points int) 

insert @songs values (1, 1, 1); insert @songs values (2, 1, 20); 
insert @songs values (3, 1, 3); insert @songs values (3, 0, 11); 
insert @songs values (4, 0, 4); insert @songs values (6, 0, 2); 

select row_number() over(order by points desc) as RankingPosition, songkey, dropable, points 
from @Songs 

しかし、次の条件を追加:基本的に私はこのような何かをしようとしている「dropable」曲は彼らのランキングを失う、彼らがトップ3をしない場合、これは「SongKey#2ウォンを意味します(nullです)しかし、#4と#6ではなく#が落ちます。だから、出力は次のようになります。

  • PositionRank 1 - Songkey 2
  • PositionRank 2 - Songkey 3
  • PositionRank 3 - Songkey 4
  • PositionRank 4 - Songkey 6
  • PositionRankヌル - Songkey 4
  • PositionRankヌル - Songkey 1つの

順位が決定されるB yポイントですが、条件があります。

+0

、2番目のSELECT句は、おそらく 'N'の列を持っているdoesntの曲テーブルを使用しています。 NumberSongPairに参加する必要があります。とにかく、あなたのテーブル構造を知るのに役立つかもしれません –

+1

あなたはあなたのランキングロジックを簡単な英語で記述できますか?あなたの問題は、再帰ではなくRANK OVER関数で簡単に解決できますが、ランクをどのように計算しているかによって異なります。 –

+0

「編集」の後に投稿に追加しました。再帰が必要なのは、条件に基づいて増分値をスキップし、後で増分を続けることが必要な場合があるためです。 – Parmenides

答えて

1
WITH songs (songkey, dropable, points) AS (
    SELECT 1, 1, 1 UNION ALL 
    SELECT 2, 1, 20 UNION ALL 
    SELECT 3, 1, 3 UNION ALL 
    SELECT 4, 0, 4 UNION ALL 
    SELECT 5, 0, 11 UNION ALL 
    SELECT 6, 0, 2 
), 
preliminaryRanking AS (
    SELECT 
    rank1 = ROW_NUMBER() OVER (ORDER BY points DESC), 
    * 
    FROM songs 
), 
finalRanking AS (
    SELECT 
    rank2 = ROW_NUMBER() OVER (
     ORDER BY 
     CASE 
      WHEN rank1 <= 3 OR dropable = 0 THEN rank1 
      ELSE CAST(0x7FFFFFFF AS int) 
     END 
    ), 
    * 
    FROM preliminaryRanking 
) 
SELECT 
    PositionRank = CASE WHEN rank1 <= 3 OR dropable = 0 THEN rank2 END, 
    songkey, dropable, points 
FROM finalRanking 
ORDER BY rank1 

出力:あなたの最初のCTEのために

PositionRank   songkey  dropable points 
-------------------- ----------- ----------- ----------- 
1     2   1   20 
2     5   0   11 
3     4   0   4 
NULL     3   1   3 
4     6   0   2 
NULL     1   1   1 
0

rownumberを使用する必要があります。私はあなたが望む100%を理解していませんが、これはrownumberを使用する方法の例です。あなたのCorrentスクリプトがうまくいかない理由は、あなたがNumberSongPairとSongsの組合の下に参加していないからです。あなたが私はあなたが欲しいものを行うためのスクリプトを書きたい場合は、私はいくつかのサンプルデータを、期待される成果とその背後にあるロジックを提供

declare @songs table (songkey int, base int, ctr int) 

insert @songs values (1, 1, 1) 
insert @songs values (2, 1, 1) 
insert @songs values (3, 1, 1) 

;WITH wrn AS (
select row_number() over(order by (select 1)) [rn], * from @Songs) 
,a as 
(
SELECT case 
when (base + 1)%2=0 then ctr 
when ctr <=20 then ctr 
else null end n, 
case when (base + 1)%2=0 then ctr + 1 
else ctr end CTR FROM WRN 
) 
SELECT n FROM a 

にそれらを結合することは何もないようです。

+0

私は注文に基づいて2つを結合することについてあなたが言ったことを試してみます。たぶん、各テーブルの単純なROW_NUMBER()をONの結合として使用します。 – Parmenides

関連する問題