我希望我的应用程序的用户使用名为Order的字段更改记录的顺序。我生成了一些脚本以便更改记录的顺序,但我认为应该有更优化的方法来完成它。
我的测试表名为MyTable。表的ID称为ID,订单字段称为Order。
我的SQL命令如下:
上移
Declare @ID int = 3;
Declare @Order int = (SELECT [Order] FROM MyTable WHERE ID = @ID);
Declare @PreviousID int = (SELECT MAX(ID) FROM MyTable WHERE [Order] < @Order);
Update MyTable SET [Order] = @Order - 1 WHERE ID = @ID;
Update MyTable SET [Order] = @Order WHERE ID = @PreviousID
下移
Declare @ID int = 3;
Declare @Order int = (SELECT [Order] FROM MyTable WHERE ID = @ID);
Declare @NextID int = (SELECT MIN(ID) FROM MyTable WHERE [Order] > @Order);
Update MyTable SET [Order] = @Order + 1 WHERE ID = @ID;
Update MyTable SET [Order] = @Order WHERE ID = @NextID
转到顶部
Declare @ID int = 3;
Declare @MinimumOrder int = (SELECT Min([Order]) FROM MyTable);
Update MyTable SET [Order] = @MinimumOrder - 1 WHERE ID = @ID;
移到底部
Declare @ID int = 3;
Declare @MaximumOrder int = (SELECT Max([Order]) FROM MyTable);
Update MyTable SET [Order] = @MaximumOrder + 1 WHERE ID = @ID;
这些SQL命令没有问题。它也可以为Order字段设置负数。
我还想生成一个更新Order文件的SQL脚本,以便它更新Order文件,以便Order从1开始并将其值增加1.这很有用,因为有时我们可能会删除记录或我的脚本可能会产生负序号码。例如,如果您尝试使用Order = 1向上移动记录,那么它将使Order取值0,如果再次执行,则取值-1等。
答案 0 :(得分:1)
如果您将排序列标准化为从1
到项目数的值,则可以使用下面的示例代码来维护订单。一般技术是选择where
语句的update
子句中的所有受影响的行,并使用case
表达式来适当地更新排序列。
-- Sample data.
declare @Samples as Table ( SampleId Int Identity, DisplayOrder Int, Name VarChar(20) );
insert into @Samples ( DisplayOrder, Name ) values
( 1, 'Chutney' ), ( 2, 'Marshmallows' ), ( 3, 'Carrots' ), ( 4, 'Cheddar' );
select * from @Samples order by DisplayOrder;
-- Swap display orders so that the target row is moved to the target display position.
declare @TargetId as Int = 2;
declare @TargetDisplayOrder as Int = 1;
update @Samples
set DisplayOrder = case
when SampleId = @TargetId then @TargetDisplayOrder
else ( select DisplayOrder from @Samples where SampleId = @TargetId ) end
where SampleId in ( @TargetId,
( select SampleId from @Samples where DisplayOrder = @TargetDisplayOrder ) );
select * from @Samples order by DisplayOrder;
-- Move the target row up one position in the display order.
set @TargetId = 3;
update @Samples
set DisplayOrder = case
when SampleId = @TargetId then DisplayOrder - 1
else DisplayOrder + 1 end
where SampleId in ( @TargetId,
( select SampleId from @Samples where DisplayOrder =
( select DisplayOrder from @Samples where SampleId = @TargetId ) - 1 ) );
select * from @Samples order by DisplayOrder;
-- Move the target row down one position in the display order.
set @TargetId = 2;
update @Samples
set DisplayOrder = case
when SampleId = @TargetId then DisplayOrder + 1
else DisplayOrder - 1 end
where SampleId in ( @TargetId,
( select SampleId from @Samples where DisplayOrder =
( select DisplayOrder from @Samples where SampleId = @TargetId ) + 1 ) );
select * from @Samples order by DisplayOrder;
-- Move the target row up to the top in the display order.
set @TargetId = 1;
update @Samples
set DisplayOrder = case
when SampleId = @TargetId then 1
else DisplayOrder + 1 end
where DisplayOrder <= ( select DisplayOrder from @Samples where SampleId = @TargetId );
select * from @Samples order by DisplayOrder;
-- Move the target row down to the bottom in the display order.
set @TargetId = 3;
update @Samples
set DisplayOrder = case
when SampleId = @TargetId then ( select Max( DisplayOrder ) from @Samples )
else DisplayOrder - 1 end
where DisplayOrder >= ( select DisplayOrder from @Samples where SampleId = @TargetId );
select * from @Samples order by DisplayOrder;
请注意,如果您使用多个语句来执行工作,例如insert
新行,然后update
将其移动到所需的顺序,您需要将语句包装在事务中(具有合适的隔离级别),以防止多个用户破坏数据。
答案 1 :(得分:0)
我不知道这是否是最好的方法,但我设法使用游标。
DECLARE @i int = 1;
DECLARE @ID int
DECLARE db_cursor CURSOR FOR
SELECT ID FROM MyTable ORDER BY [Order]
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @ID
WHILE @@FETCH_STATUS = 0
BEGIN
update MyTable set [Order] = @i WHERE ID = @ID;
SET @i = @i + 1;
FETCH NEXT FROM db_cursor INTO @ID
END
CLOSE db_cursor
DEALLOCATE db_cursor
如果有更好的方法,请通知我。
答案 2 :(得分:0)
在合并订单价值方面,T-SQL的ROW_NUMBER()操作可能对您有用。
这是一个示例,说明如何使用此功能整合订单值,而不会影响该订单中商品的排名:
/* declare placeholder and populate with test values */
declare @MyTable table (ID bigint identity(1,1), [Order] bigint)
insert into @MyTable ([Order])
VALUES
(1),
(3),
(2),
(5),
(-4),
(13),
(0)
/* Look at values we've just inserted */
select * from @MyTable order by [Order]
/* Show how ROW_NUMBER() can apply a consolidated ranking based on our existing order */
select *, ROW_NUMBER() over (order by [Order] asc) as sort from @MyTable
/* Apply that consolidated ranking to update the order values */
update @MyTable
set [Order] = consolidated.sort
from
(
select ID as refID, ROW_NUMBER() over (order by [Order] asc) as sort from @MyTable
) consolidated
where consolidated.refID = ID
/* Final display of updated table */
select * from @MyTable order by [Order]
理想情况下,从一开始就需要花些时间来管理和保持数据清理。
部分内容是数据库结构和规范化,请查看以下内容:
如果其中任何一个属实,您可能希望将排序分解为单独的表以用于数据完整性目的(并且由于事务锁定和事情,即使您不这样做也可能值得做)
除了数据库设计之外,还有必要了解如何处理数据操作以修改记录顺序。
如果我们使用具有N条记录的表格,并且这些记录具有密集的订单(根据上面的查询演示,订单值为1,2,3,4,5等) 。),然后任何时候我们对该订单进行了更改,我们必须更新表中现有订单值的很多。
例如:
补偿这一点的一种方法是使用抵消计算排名 - 而不是按1,2,3...
排序,而是使用更大的值,例如10,20,30...
。这使您可以处理用户的订购更改而无需立即加载大量数据(将订单移至订单2?将其插入位置15,介于10和20之间),然后您可以稍后优化订单。 / p>
答案 3 :(得分:-1)
以下不会获得[订单]中的上一项(除非运气好)。
String SERVICE_URL = "http://hostIpAddress:8080/JiraUpdate/rest/createin/jira/createticket?"; // hostIpaddress is our server ip
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
System.out.println("SERVICE_URL=" + SERVICE_URL);
WebResource webResource = client.resource(UriBuilder.fromUri(SERVICE_URL).build());
String input = "{\"fields\":{\"project\":{\"key\":\"Invoicing\"},\"summary\":\"REST Test\",\"description\": \"Creating of an issue using project keys and issue type names using the REST API\",\"issuetype\":{\"name\":\"Bug\"}}}";
ClientResponse response = webResource.header("Content-Type","application/json;charset=UTF-8").post(ClientResponse.class,input);
与Declare @PreviousID int = (SELECT MAX(ID) FROM MyTable WHERE [Order] < @Order);
相同的问题。