拆分一副牌,并像洗牌一样返回结果

bee*_*eks 5 sql-server t-sql

假设我有一张桌子,上面有一副牌,编号为 01-52。我可以返回顶部和底部的卡片,就好像我通过执行以下操作将联合选择查询的每一侧握在我的左手和右手上:

select top 26 * from DeckOfCards order by CardNumber desc
union all
select top 26 * from DeckOfCards order by CardNumber asc
Run Code Online (Sandbox Code Playgroud)

这将是平分秋色。

但是我怎么能让 SQL Server 将返回的结果交织在一起,就好像我已经拿走了那个联合的两个部分,一个在我的左手,另一个在我的右手,然后像一副纸牌一样洗牌一次?

IE:CardNumber 52,后跟 1,顺序如下:52, 1, 51, 2, 50, 3, 49, 4, etc...

这不是一个家庭作业问题,只是当我试图闭上眼睛时脑海中闪过的那些事情之一。:)

Pau*_*ite 6

我想提供一种避免排序的替代解决方案(使用Serpiton 的答案中的示例数据- 谢谢!)。这应该可以使用ROW_NUMBER,但查询优化器目前无法将其投影识别为唯一的。所以:

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;
Run Code Online (Sandbox Code Playgroud)

SQLFiddle

输出:

输出

执行计划:

执行计划


Ser*_*ton 5

一点数学可以帮助实现这一目标

SELECT CardNumber
FROM   DeckOfCards 
ORDER BY (1 - CAST(CardNumber / 27 as bit)) * (CardNumber* 2)
       + (CAST(CardNumber/ 27 as bit)) * (1 + (52 - CardNumber) * 2)
Run Code Online (Sandbox Code Playgroud)

CAST(CardNumber / 27 as bit) 为低于 27 的卡号返回 0,为高于 26 的卡号返回 1,使用它可以为两个不同的块创建不同的顺序:

  • (1 - CAST(CardNumber / 27 as bit)) * (CardNumber* 2) 将前 26 张卡放在偶数位置,因为第一个成员为那张卡为 1,另一张为 0
  • (CAST(CardNumber/ 27 as bit)) * (1 + (52 - CardNumber) * 2)将第二张 26 卡放在奇数位置,例如(1 + (52 - CardNumber) * 2)将按降序返回奇数

SQLFiddle example 将订单公式作为第二列,看看它是如何工作的

  • 仅供参考,额外的连接是有意的,仅混洗 id(没有任何其他属性)。第二种解决方案确实在语义上相似,尽管它没有避免数据大小排序,这是我陈述的目标。有各种各样的(哈!)小问题,比如 `53 - CardNumber` 不是一个保持顺序的函数,但我认为除了我之外没有人会关心这个。对于 52 行的输入,您可能不在乎是正确的;然而,在较大的任务中,通过正确考虑顺序保留来避免排序可能很重要。 (2认同)