是否可以重新排序SQL数据库中的行? 例如;如何交换第2行和第3行的值?
行的顺序对我很重要,因为我需要根据顺序显示值。
感谢所有答案。但'Order by'对我不起作用。
例如,我在数据库中放了一个书签列表。 我想根据查询得到的结果进行显示。 (不按字母顺序排列)。就在插入它们的时候。
但是用户可以重新排列书签的位置(以他/她想要的任何方式)。所以我不能使用'order by'。
一个例子是如何在firefox中的书签中显示书签。用户可以轻松切换位置。我怎么能在DB中提到它?
谢谢。
答案 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,这意味着不必更新许多(通常在实践中只有几个)行。
简而言之,我会做以下事情:
[[id, sort_order], [id2, sort_order], ...]
update item set sort_order=SORT_ORDER where id=ID
(executemany)
(如果将项目移动到另一个容器,更新“容器外键”后,根据应用程序移动第一个或最后一个。)
(如果更新涉及大量项目,我认为此解决方案不是一个好方法。)
我在http://wannapy.blogspot.com/2010/11/reorder-rows-in-sql-database.html上使用python和mysql做了一个例子(复制并试一试)以及一些额外的解释。
答案 8 :(得分:0)
在回复your post here时,您可能正在寻找的答案是:
要按时间顺序排序,请添加DateAdded
或类似的列,其中包含datetime
或smalldatetime
数据类型。
在插入数据库的所有方法中,请确保在CURRENT_TIMESTAMP
列中插入DateAdded
。
在查询数据库的方法上,在查询字符串的末尾添加ORDER BY DateAdded
。
永远不要依赖数据库系统中的物理位置。它可能工作的时间最多,但绝对不是所有时间。
答案 9 :(得分:0)
首先,我同意大家的看法,表中的顺序无关紧要。使用您更新的单独[SortOrder]列并包含Order By子句。
也就是说,SQL Server数据库确实允许表上的单个“聚簇索引”实际上强制在基础表存储中的位置。如果您有一个大数据集并且始终按特定内容查询,则非常有用。
答案 10 :(得分:0)
这个问题缺乏任何可以让任何人给你正确答案的细节。显然,您可以将记录读入内存,然后更新它们。但这在很多不同的层面都很糟糕。
问题是这样的。根据实际实现的模式,记录物理写入磁盘的方式存在逻辑。有时它们按插入顺序写入,有时它们在块之间插入空格(参见范围)。
因此,如果不交换列数据,就不可能改变物理顺序;这对各种指数产生了深远的影响。您无需更改逻辑顺序。
当我阅读您的更新时......我只能理解您可能拥有多个用户,并且每个用户都有他们想要订购的书签。看起来您需要第二个表作为用户和书签之间的交集。然后你需要的只是一个内连接和一个命令。
但是没有足够的信息来提供完整的解决方案。
答案 11 :(得分:0)
在表中添加position
列并存储为简单整数。
如果您需要支持多个用户或列表,最好的办法是创建书签表,用户表和表格来链接它们。
id,url
id,name
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和“表格顺序”将是一个更明智的答案(如果是这样,那么他是最好的解决方案,而无需理会此答案)