代码之家  ›  专栏  ›  技术社区  ›  Tigraine

在保持排序的同时将排序列表保存到数据库的最佳方法

  •  65
  • Tigraine  · 技术社区  · 16 年前

    我想知道在过去的几年里,是否有人能很好地解决我多次遇到的问题。

    我有一个购物车,我的客户明确要求它的订单是重要的。所以我需要把命令持久化到数据库。

    显而易见的方法是简单地插入一些orderfield,在这里我将把数字0分配给n,然后按这种方式排序。

    但这样做会使重新排序更加困难,我不知何故觉得这个解决方案有点脆弱,总有一天会回来找我。

    (我将C 3,5与nhibernate和SQL Server 2005结合使用)

    谢谢你

    12 回复  |  直到 8 年前
        1
  •  24
  •   Galwegian    16 年前

    fwiw,我认为你的建议(即向数据库提交订单)并不是解决你问题的一个坏办法。我也认为这可能是最安全/最可靠的方法。

        2
  •  46
  •   Community CDub    13 年前

    好的,这里是我的解决方案,它可以让在这个线程中发生的任何人更容易地进行编程。诀窍是能够在一次更新中更新插入/删除上方或下方的所有订单索引。

    在表中使用SQL查询支持的数值(整数)列

    CREATE TABLE myitems (Myitem TEXT, id INTEGER PRIMARY KEY, orderindex NUMERIC);
    

    要删除OrderIndex 6中的项目:

    DELETE FROM myitems WHERE orderindex=6;    
    UPDATE myitems SET orderindex = (orderindex - 1) WHERE orderindex > 6;
    

    交换两个项目(4和7):

    UPDATE myitems SET orderindex = 0 WHERE orderindex = 4;
    UPDATE myitems SET orderindex = 4 WHERE orderindex = 7;
    UPDATE myitems SET orderindex = 7 WHERE orderindex = 0;
    

    也就是说,不使用0,所以将它用作虚拟项,以避免出现不明确的项。

    在3插入:

     UPDATE myitems SET orderindex = (orderindex + 1) WHERE orderindex > 2;
     INSERT INTO myitems (Myitem,orderindex) values ("MytxtitemHere",3)
    
        3
  •  30
  •   Leniel Maccaferri    11 年前

    最佳解决方案是 Doubly Linked list . o(1)用于除索引以外的所有操作。但是,除了所需项上的WHERE子句外,没有任何东西可以快速索引SQL。

    0,10,20类型失败。序列列1失败。浮动序列列在组移动时失败。

    双链表的添加、删除、删除组、添加组、移动组操作相同。单链表也可以。不过,在我看来,使用SQL进行双重链接更好。单链表要求您拥有整个列表。

        4
  •  9
  •   Js.    15 年前

    如何使用链接列表实现?有一列将保存下一项的值(订单号)。我认为在中间插入订单时,它是最容易使用的。无需重新编号。

        5
  •  5
  •   Binary Worrier    12 年前

    不幸的是,这里没有魔法子弹。你不能保证任何 SELECT 没有ORDER BY子句的语句。您需要添加列并围绕它进行编程。

    我不知道我会建议在订单序列中添加间隙,这取决于列表的大小和网站上的点击量,您在处理逻辑方面可能会获得很少的收益(您仍然需要满足所有间隙都已用完的情况)。我会仔细看看这会给你带来什么好处。

    对不起,我不能再提供更好的服务了,希望能有所帮助。

        6
  •  3
  •   Adam    16 年前

    我根本不推荐A、AA、B、BA、BB方法。有很多额外的处理涉及到确定层次结构和插入之间的条目一点也不有趣。

    只需添加一个orderfield,integer。不要使用间隙,因为在下一次中间插入时必须使用非标准的“步骤”,或者必须先重新同步列表,然后添加新条目。

    拥有0…n很容易重新排序,如果您可以使用SQL之外的数组方法或列表方法重新排序整个集合,然后更新每个条目,或者您可以确定插入到哪里,以及相应地在它之后或之前的每个条目+1或-1。

    一旦你有了一个专门为它写的小图书馆,它将是一块蛋糕。

        7
  •  1
  •   Jack Ryan    16 年前

    我只需要插入一个订单字段。这是最简单的方法。如果客户可以对字段重新排序,或者您需要在中间插入,那么只需重写该批中所有项目的订单字段。

    如果您发现这一限制是由于插入和更新的性能不佳,那么可以使用varchar字段而不是整数。这使得插入时的精度非常高。例如,要在“a”和“b”项之间插入,可以插入按“a a”排序的项。不过,对于一辆购物车来说,这几乎是多余的。

        8
  •  1
  •   redzedi    16 年前

    在购物车项目之上的抽象层次上,比如cartorder(其中cartem为1-n),您可以维护一个名为itemorder的字段,该字段可能只是相关购物车项目记录的ID(pk)的逗号分隔列表。它将位于应用程序层,您需要解析它并相应地安排项目模型。这种方法的最大优点是在重新整理顺序时,可能不会对单个对象进行更改,但是由于顺序作为索引字段持久存在于顺序项目表行中,因此必须为每一行发出更新命令来更新其索引字段。 请告诉我你对这种方法的批评,我很想知道这种方法会以何种方式失败。

        9
  •  1
  •   Bijan Jesse Wolgamott    10 年前

    我解决了它 务实地 这样地:

    1. 订单在用户界面中定义。

    2. 后端获取一个post请求,该请求包含列表中每个项目的ID和相应位置。

    3. 我启动一个事务处理并更新每个ID的位置。

    完成。

    所以订购费用很高,但是阅读订购清单是非常便宜的。

        10
  •  0
  •   harriyott Erik Funkenbusch    16 年前

    我建议在订单号中保留空白,因此,不要使用1、2、3等,而是使用10、20、30…如果你只需要再插入一个项目,你可以把它放在15,而不是在那个时候重新排序所有的项目。

        11
  •  0
  •   sindre j    16 年前

    好吧,我想简短的回答是:

    在CartContents表中创建一个AutoIdentity主键,然后按正确的自上而下顺序插入行。然后,通过按主键排序从表中进行选择,AutoIdentity列将给出相同的列表。通过这样做,您必须删除所有项目,然后重新插入,以防更改购物车内容。(但这仍然是一种非常干净的方法)如果这不可行,那么按照其他人建议的顺序进行操作。

        12
  •  -1
  •   yglodt    9 年前

    当我使用 Hibernate ,需要保存 @OneToMany 我用的是 Map 而不是 List .

    @OneToMany(fetch = FetchType.EAGER, mappedBy = "rule", cascade = CascadeType.ALL)
    @MapKey(name = "position")
    @OrderBy("position")
    private Map<Integer, RuleAction>    actions             = LazyMap.decorate(new LinkedHashMap<>(), FactoryUtils.instantiateFactory(RuleAction.class, new Class[] { Rule.class }, new Object[] { this }));
    

    在这个Java示例中, position 是的整数属性 RuleAction 所以顺序就是这样持续的。我猜在C中,这看起来很相似。