如何在sql数据库中重新排序行

时间:2009-05-01 18:34:54

标签: sql

是否可以重新排序SQL数据库中的行? 例如;如何交换第2行和第3行的值?

行的顺序对我很重要,因为我需要根据顺序显示值。


感谢所有答案。但'Order by'对我不起作用。

例如,我在数据库中放了一个书签列表。 我想根据查询得到的结果进行显示。 (不按字母顺序排列)。就在插入它们的时候。

但是用户可以重新排列书签的位置(以他/她想要的任何方式)。所以我不能使用'order by'。

一个例子是如何在firefox中的书签中显示书签。用户可以轻松切换位置。我怎么能在DB中提到它?

谢谢。

14 个答案:

答案 0 :(得分:67)

听起来你需要像“ListOrder”这样的另一个专栏。所以你的表可能看起来像:

BookMark ListOrder
======== =========
  d        1
  g        2
  b        3
  f        4
  a        5

然后你可以“按ListOrder排序。”

Select * from MyTable Order By ListOrder

如果用户一次只能移动一个书签,则可以使用整数作为ListOrder,并交换它们。例如,如果用户想要将“f”向上移动一行:

Update MyTable
    Set ListOrder=ListOrder+1
        Where ListOrder=(Select ListOrder-1 From MyTable where BookMark='f')

Update MyTable
    Set ListOrder=ListOrder-1
        Where BookMark='f'

如果用户可以一次向上或向下移动多个行,那么您需要重新排序一个段。例如,如果用户想要将“f”移动到列表顶部,则需要:

update MyTable
    Set ListOrder=ListOrder+1
        where ListOrder>=1 -- The New position
            and ListOrder <(Select ListOrder from MyTable where BookMark='f')

 update MyTable
     Set ListOrder=1 -- The New Position
         Where Bookmark='f'

答案 1 :(得分:18)

正如其他人所提到的,依赖数据库表的物理顺序并不是一个好主意。关系表在概念上更像是无序集而不是有序列表。假设某种物理秩序可能导致不可预测的结果。

您需要的是一个单独的列,用于存储用户首选的排序顺序。但是您仍然需要在查询中执行某些操作以按顺序显示结果。

可以通过创建聚簇索引来指定数据库中记录的物理顺序,但这不是您希望在任意用户指定的基础上执行的操作。它可能仍会导致意想不到的结果。

答案 2 :(得分:9)

ORDER BY查询中使用SELECT。例如,要按用户的姓氏排序,请使用:

SELECT * FROM User ORDER BY LastName

答案 3 :(得分:4)

实际数据库中行的顺序无关紧要。

您应该在查询中使用ORDER BY子句根据需要对其进行排序。

答案 4 :(得分:3)

数据库可以以他们想要的任何方式存储数据。使用“order by”子句是唯一方式来保证数据的排序。在您的书签示例中,您可以有一个指示排序的整数字段,然后在用户移动时更新该字段。然后按ORDER BY该列以正确的顺序获取内容。

答案 5 :(得分:1)

我想一个简单的order by会是你想要的吗?

select my_column from my_table order by my_order_column;

答案 6 :(得分:1)

正如其他人所说的那样,使用了一个订单 永远不要依赖物理表中存在的订单数据,始终以您正在使用的数据为基础,无论是一个或多个关键字段。

答案 7 :(得分:1)

我有一个解决方案,我已经使用了几次。我在表中保留了一个额外的字段“sort_order”,并在重新排序时更新它。我已经使用了这种情况,当我有一些带有物品的容器时,物品的顺序应该可以在容器内编辑。重新排序时,我只更新当前容器中项目的sort_order,这意味着不必更新许多(通常在实践中只有几个)行。

简而言之,我会做以下事情:

  1. 将sort_order字段添加到项目表
  2. 插入新行时,我设置了sort_order = id
  3. 重新排序时(需要移动项目的ID,以及之后插入项目的ID):
    • 通过sort_order
    • 从容器= ID顺序的项目中选择id,sort_order
    • 从两个数组中的行中分割id和sort_order
    • 删除要从id-list
    • 移动的项目的ID
    • 之后插入要插入的项目的ID之后插入要移动的项目的ID
    • 将id列表和sort_order列表合并为二维数组,如[[id, sort_order], [id2, sort_order], ...]
    • 使用合并列表
    • 运行update item set sort_order=SORT_ORDER where id=ID(executemany)
  4. (如果将项目移动到另一个容器,更新“容器外键”后,根据应用程序移动第一个或最后一个。)

    (如果更新涉及大量项目,我认为此解决方案不是一个好方法。)

    我在http://wannapy.blogspot.com/2010/11/reorder-rows-in-sql-database.html上使用python和mysql做了一个例子(复制并试一试)以及一些额外的解释。

答案 8 :(得分:0)

在回复your post here时,您可能正在寻找的答案是:

要按时间顺序排序,请添加DateAdded或类似的列,其中包含datetimesmalldatetime数据类型。

在插入数据库的所有方法中,请确保在CURRENT_TIMESTAMP列中插入DateAdded

在查询数据库的方法上,在查询字符串的末尾添加ORDER BY DateAdded

永远不要依赖数据库系统中的物理位置。它可能工作的时间最多,但绝对不是所有时间。

答案 9 :(得分:0)

首先,我同意大家的看法,表中的顺序无关紧要。使用您更新的单独[SortOrder]列并包含Order By子句。

也就是说,SQL Server数据库确实允许表上的单个“聚簇索引”实际上强制在基础表存储中的位置。如果您有一个大数据集并且始终按特定内容查询,则非常有用。

答案 10 :(得分:0)

这个问题缺乏任何可以让任何人给你正确答案的细节。显然,您可以将记录读入内存,然后更新它们。但这在很多不同的层面都很糟糕。

问题是这样的。根据实际实现的模式,记录物理写入磁盘的方式存在逻辑。有时它们按插入顺序写入,有时它们在块之间插入空格(参见范围)。

因此,如果不交换列数据,就不可能改变物理顺序;这对各种指数产生了深远的影响。您无需更改逻辑顺序。

当我阅读您的更新时......我只能理解您可能拥有多个用户,并且每个用户都有他们想要订购的书签。看起来您需要第二个表作为用户和书签之间的交集。然后你需要的只是一个内连接和一个命令。

但是没有足够的信息来提供完整的解决方案。

答案 11 :(得分:0)

在表中添加position列并存储为简单整数。

如果您需要支持多个用户或列表,最好的办法是创建书签表,用户表和表格来链接它们。

  • 书签:id,url
  • 用户:id,name
  • users_bookmarks:user_id, bookmark_id, position, date_created

假设在插入行时填充date_created,您可以根据日期获得辅助列表排序。

select bookmark_id from users_bookmarks where user_id = 1 order by position, date_created;

答案 12 :(得分:0)

这是一个存储的过程脚本,用于在MySQL中递增或递减(一次一个)

注意,MySQL不允许您在要更新的同一查询中进行选择,因此上述答案不起作用。

如果您要分别递增/递减,那么我也将其设置为如果在上/下没有项目分别返回错误。

openssl base64

致电

DELIMITER $$
CREATE PROCEDURE `spReorderSequenceItems` (
  IN _SequenceItemId INT,
  IN _SequenceId INT,
  IN IncrementUp TINYINT,
  OUT Error VARCHAR(255)
)

BEGIN
  DECLARE CurrentPosition INT;

  SELECT Position INTO CurrentPosition
  FROM tblSequenceItems
  WHERE SequenceItemId = _SequenceItemId;

  IF IncrementUp = 1 THEN
    IF (
      SELECT Position
      FROM tblSequenceItems 
      WHERE Position = CurrentPosition + 1 AND SequenceId = _SequenceId
    ) THEN
      UPDATE tblSequenceItems
        SET Position = Position - 1
        WHERE Position = CurrentPosition + 1 AND SequenceId = _SequenceId;
      UPDATE tblSequenceItems
        SET Position = Position + 1
        WHERE SequenceItemId = _SequenceItemId;
    ELSE 
      SELECT 'No Item Above' AS _Error INTO Error;
    END IF;
  ELSE
    IF (
      SELECT Position
      FROM tblSequenceItems 
      WHERE Position = CurrentPosition - 1 AND SequenceId = _SequenceId
    ) THEN
      UPDATE tblSequenceItems
        SET Position = Position + 1
        WHERE Position = CurrentPosition - 1 AND SequenceId = _SequenceId;
      UPDATE tblSequenceItems
        SET Position = Position - 1
        WHERE SequenceItemId = _SequenceItemId;
    ELSE
      SELECT 'No Item Below' AS _Error INTO Error;
    END IF;
  END IF;
END
$$
DELIMITER ;

答案 13 :(得分:0)

在这样的时候,我想起了《黑客帝国》中的一句话:“不要尝试对数据库进行排序。这是不可能的。相反,只能意识到事实……没有顺序。然后您将看到它自己订购的桌子,是您订购桌子的。”

通过GUI使用MySQL时,总是要做出决定。如果您运行类似SELECT * FROM users的程序,则MySql始终会决定是否按某个字段对它进行排序。通常,这将是主键。

+----------------
| id | name     |
-----------------
| 1  | Brian    |
| 2  | Carl     |
| 3  | Albert   |
-----------------

在查询中添加ORDER BY命令时,它将决定是否按其他字段排序。

例如Select * From users ORDER BY name将产生:

+----------------
| id | name     |
-----------------
| 3  | Albert   |
| 1  | Brian    |
| 2  | Carl     |
-----------------

因此,对于您的问题,您似乎想更改表显示此信息的默认顺序。为此,请查看您的“主键”字段 是。对于大多数实际目的,具有唯一的识别自然数往往可以解决问题。 MySQL为此提供了一个AUTO_INCREMENT函数。创建表时,其外观类似于field_name int NOT NULL AUTO_INCREMENT

所有这些都是说:如果您想更改“行顺序”,则需要更新此值。但是,由于标识符是其他表用来引用您的字段的东西,因此这看起来有些鲁ck。

例如,如果您去了UPDATE table Set id = 1 where id = 2;,则此操作最初将失败,因为id字段最终将都是相同的值,并且将使PrimaryKey检查失败(该检查既坚持唯一性又具有值集)。您可以通过连续运行三个更新语句来解决这个问题:

UPDATE users Set id = 100000000 where id = 1;
UPDATE users Set id = 1 where id = 2;
UPDATE users Set id = 2 where id = 100000000;

这将导致该表的行看起来像:

+----------------
| id | name     |
-----------------
| 1  | Carl     |
| 2  | Brian    |
| 3  | Albert   |
----------------+

从技术上讲,该表可以重新排序,但这是一个气泡。 MySQL是关系数据库,这意味着依赖于该数据的所有表都将被指向错误的数据。例如,我有一个存储生日的表,它引用了初始用户表。它的结构可能看起来像这样:

+----------------------------+
| id | user_id  | birthdate  |
+----------------------------+
| 1  | 1        | 1993-01-01 |
| 1  | 2        | 1980-02-03 |
| 1  | 3        | 1955-01-01 |
+----------------------------+

通过切换用户表上的ID,必须更新生日表上的user_id值。当然,MySQL为此做好了准备:输入“ Foreign Key Constraints”。只要将所有外键约束配置为Cascade Updates,就无需手动将引用更改为更改的每个值。

这些查询将需要大量的人工操作,并有可能削弱您数据的完整性。如果您希望定期对字段进行排名和重新排序,则使用the answer posed by Mike Lewis on this question和“表格顺序”将是一个更明智的答案(如果是这样,那么他是最好的解决方案,而无需理会此答案)