尝试通过声明数据在T-SQL中排序时出错

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (23)

我正在尝试学习T-SQL编程,我注意到我的下面的代码有错误。此代码用于学习如何在没有顺序的情况下进行排序,它看起来像冒泡排序算法。

在我尝试进行排序后,我首先创建表并插入随机数

码:

CREATE TABLE #NumbersArray
(
    ArrayIndex INT PRIMARY KEY,
    Value INT
)
GO

INSERT INTO #NumbersArray(ArrayIndex, Value)
    SELECT 0, 5
    UNION ALL
    SELECT 1, 1 
    UNION ALL
    SELECT 2, 3 
    UNION ALL
    SELECT 3, 4
    UNION ALL
    SELECT 4, 2

SELECT * FROM #NumbersArray
GO    

DECLARE @CurrentIndex INT,
        @MaxIndex INT,
        @swapoccured BIT

SET @swapoccured = 1
SET @MaxIndex = (SELECT COUNT(*) - 1 FROM #NumbersArray)

WHILE (@swapoccured = 1)
BEGIN
    SET @swapoccured = 0
    SET @CurrentIndex = 0

    WHILE (@CurrentIndex < @MaxIndex)
        DECLARE @value1 INT
        DECLARE @value2 INT
    BEGIN  -- Mistake was here. I put the begin in wrong place
        SET @value1 = (SELECT Value FROM #NumbersArray WHERE ArrayIndex = @CurrentIndex)
        SET @value2 = (SELECT Value FROM #NumbersArray WHERE ArrayIndex = @CurrentIndex + 1)

        IF (@value1 > @value2)
        BEGIN
            UPDATE #NumbersArray 
            SET Value = @value2 
            WHERE ArrayIndex = @CurrentIndex

            UPDATE #NumbersArray 
            SET Value = @value1 
            WHERE ArrayIndex = @CurrentIndex + 1

            SET @swapoccured = 1
         END

         SET @CurrentIndex = @CurrentIndex + 1
    END
END

SELECT * FROM #NumbersArray

因此,我认为我的代码库存在排序中间,而我从未完成,但我可以确定问题是什么。

提问于
用户回答回答于

首先,如果没有ORDER BY子句(阅读@ ZoharPeled的答案),订购数据是不可能的,所以这不是合适的方法。这样我只关注你的错误。原因是第二个WHILE循环。如果没有BEGIN .. END这个循环,只需无休止地声明一个变量:WHILE (@CurrentIndex < @MaxIndex) DECLARE @value1 INT

这可能就是你想要的(用它来学习如何使用WHILE循环,而不是如何订购数据):

CREATE TABLE #NumbersArray
(
    ArrayIndex INT PRIMARY KEY,
    Value INT
)
GO

INSERT INTO #NumbersArray(ArrayIndex, Value)
    SELECT 0, 5
    UNION ALL
    SELECT 1, 1 
    UNION ALL
    SELECT 2, 3 
    UNION ALL
    SELECT 3, 4
    UNION ALL
    SELECT 4, 2

SELECT * FROM #NumbersArray
GO    

DECLARE @CurrentIndex INT,
        @MaxIndex INT,
        @swapoccured BIT

SET @swapoccured = 1
SET @MaxIndex = (SELECT COUNT(*) - 1 FROM #NumbersArray)

WHILE (@swapoccured = 1)
BEGIN
    SET @swapoccured = 0
    SET @CurrentIndex = 0

    DECLARE @value1 INT
    DECLARE @value2 INT
    WHILE (@CurrentIndex < @MaxIndex)
    BEGIN
        SET @value1 = (SELECT Value FROM #NumbersArray WHERE ArrayIndex = @CurrentIndex)
        SET @value2 = (SELECT Value FROM #NumbersArray WHERE ArrayIndex = @CurrentIndex + 1)

        IF (@value1 > @value2)
        BEGIN
            UPDATE #NumbersArray 
            SET Value = @value2 
            WHERE ArrayIndex = @CurrentIndex

            UPDATE #NumbersArray 
            SET Value = @value1 
            WHERE ArrayIndex = @CurrentIndex + 1

            SET @swapoccured = 1
         END

         SET @CurrentIndex = @CurrentIndex + 1
    END
END

SELECT * FROM #NumbersArray

DROP TABLE #NumbersArray
用户回答回答于

此代码用于学习如何按顺序排序...

嗯,这根本不可能。在关系数据库中,表本质上是未排序的。确保查询返回结果顺序的唯一方法是使用该order by子句。

我正在尝试学习T-SQL编程

关于SQL的任何方言,首先要了解的是它设计用于基于集合的方法 - 意味着操作是在行集上完成的,而不是基于程序的方法(AKA RBAR - Raw by agon raw)。 您可以搜索“基于集合与程序”,并提出许多文章详细解释这些方法之间的区别。

所以,说过 - 在SQL世界中不鼓励使用循环(和嵌套循环) - 包括游标,循环甚至递归公用表表达式。 大多数情况下,您可以通过使用计数表来避免使用循环- 使用基于集合的方法更改RBAR方法,并使您的代码更加高效,并且大部分时间更容易编写,读取和维护。

扫码关注云+社区

领取腾讯云代金券