Splitting a deck of cards, and returning the results as if they were shuffled once

I wanted to provide an alternative solution (using the sample data in Serpiton's answer - thanks!) that avoids sorts. This ought to be possible using ROW_NUMBER, but the query optimizer doesn't currently recognize its projection as unique. So:

DECLARE @TopHalf AS TABLE 
(
    id integer IDENTITY (1, 1) PRIMARY KEY, 
    CardID integer NOT NULL
);

DECLARE @BottomHalf AS TABLE 
(
    id integer IDENTITY (0,1) PRIMARY KEY, 
    CardID integer NOT NULL
);

INSERT TOP (26) @TopHalf (CardID)
SELECT D.id
FROM dbo.deck AS D
ORDER BY D.id ASC;

INSERT TOP (26) @BottomHalf (CardID)
SELECT D.id
FROM dbo.deck AS D
ORDER BY D.id DESC;

SELECT 
    D.id,
    D.[card]
FROM
(
    SELECT id, CardID FROM @TopHalf AS TH
    UNION
    SELECT id, CardID FROM @BottomHalf AS BH
) AS Shuffled
JOIN dbo.deck AS D
    ON D.id = Shuffled.CardID
ORDER BY 
    Shuffled.id, 
    Shuffled.CardID;

SQLFiddle

Output:

Output

Execution plans:

Execution plans


A little math can help achieving this

SELECT CardNumber
FROM   DeckOfCards 
ORDER BY (1 - CAST(CardNumber / 27 as bit)) * (CardNumber* 2)
       + (CAST(CardNumber/ 27 as bit)) * (1 + (52 - CardNumber) * 2)

CAST(CardNumber / 27 as bit) returns 0 for the card number below 27 and 1 for the number above 26, using this it's possible to create a different order for the two different block:

  • (1 - CAST(CardNumber / 27 as bit)) * (CardNumber* 2) put the first 26 card in the even position, as the first member will be 1 for those card and 0 for the other
  • (CAST(CardNumber/ 27 as bit)) * (1 + (52 - CardNumber) * 2) will put the second 26 card in the odd position, e.g. (1 + (52 - CardNumber) * 2) will return odd values in descending order

SQLFiddle example with the order formula as a second column to see how it works