Reputation: 137
I'm having trouble with a simple auto-increment using common table expressions. (I don't want ROW_NUMBER() because I will be using conditions for my incrementing) so here is a simplified version of my problem which still doesn't work. I get this error: "Invalid column name 'n'" when I try the following:
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 )
Why can't it recognize 'n' as a newly a created incremented column? I'd even be happy just getting rid of the first select all together so long as I can keep incrementing a number as I select columns from a table.
If you are curious about my overall goals it's to ranks Songs.... with conditions with something like this:
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...
Sorry, my explanation wasn't very good. I just wanted to add another psuedo auto-incrementing column that would sometimes go null instead of increment. Basically I'm trying something like this:
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
But adding the following condition: 'dropable' songs lose their ranking (are null) if they don't make the top 3. This means SongKey #2 won't drop, but but #4 and #6 will. So the output would look like:
Rank is determined by points, but there are conditions.
Upvotes: 2
Views: 4084
Reputation: 77707
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
Output:
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
Upvotes: 1
Reputation: 44336
You should use rownumber, I don't understand 100 % what you want, but this is an example how you can use rownumber. The reason your corrent script doesn't work is because you haven't joined NumberSongPair and Songs under the union part. It seems you have nothing to join them on
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
If you want me to write a script to do what you want, provide me with some sample data, expected outcome and the logic behind it.
Upvotes: 0