순서를 유지하면서 정렬 된 목록을 데이터베이스에 저장하는 가장 좋은 방법
지난 몇 년간 제가 겪은 문제에 대한 좋은 해결책이있는 사람이 있는지 궁금합니다.
장바구니가 있는데 고객이 주문이 중요하다고 명시 적으로 요청합니다. 따라서 주문을 DB에 유지해야합니다.
명백한 방법은 숫자 0을 N에 할당하고 그런 방식으로 정렬하는 OrderField를 삽입하는 것입니다.
그러나 그렇게하면 재정렬이 더 어려워지고 어떻게 든이 솔루션이 깨지기 쉽고 언젠가 다시 돌아올 것이라고 생각합니다.
(저는 NHibernate 및 SQL Server 2005에서 C # 3,5를 사용합니다)
감사합니다
FWIW, 나는 당신이 제안하는 방식 (즉, 주문을 데이터베이스에 커밋하는 것)이 당신의 문제에 대한 나쁜 해결책이 아니라고 생각합니다. 또한 아마도 가장 안전하고 신뢰할 수있는 방법이라고 생각합니다.
Ok 여기 에이 스레드와 함께 발생하는 모든 사람이 프로그래밍을 쉽게 할 수있는 솔루션이 있습니다. 트릭은 하나의 업데이트에서 삽입 / 삭제 위 또는 아래의 모든 주문 색인을 업데이트 할 수 있다는 것입니다.
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)
최상의 솔루션은 이중 연결 목록 입니다. 인덱싱을 제외한 모든 작업에 대해 O (1). 원하는 항목의 where 절을 제외하고는 SQL을 빠르게 색인화 할 수있는 것은 없습니다.
0,10,20 유형이 실패합니다. 시퀀스 열 1이 실패합니다. 그룹 이동시 부동 시퀀스 열이 실패합니다.
이중 연결 목록은 추가, 제거, 그룹 삭제, 그룹 추가, 그룹 이동에 대한 동일한 작업입니다. 단일 연결 목록도 잘 작동합니다. 내 의견으로는 이중 링크가 SQL에 더 좋습니다. 단일 연결 목록을 사용하려면 전체 목록이 있어야합니다.
연결 목록 구현을 사용하는 것은 어떻습니까? 하나의 열이 있으면 다음 항목의 값 (주문 번호)을 보유합니다. 중간에 주문을 삽입 할 때 사용하기 가장 쉬운 방법이라고 생각합니다. 번호를 다시 매길 필요가 없습니다.
불행히도 이것에 대한 마법 총알이 없습니다. SELECT
order by 절이 없는 명세서 의 순서를 보장 할 수 없습니다 . 열을 추가하고 주위에 프로그램해야합니다.
목록의 크기와 사이트의 히트 수에 따라 순서 순서에 간격을 추가하는 것이 좋습니다. 로직 처리의 오버 헤드에 대해 거의 얻을 수 없습니다. 모든 틈새가 모두 사용 된 경우를 수용하기 위해). 나는 이것이 당신의 상황에서 당신에게 어떤 혜택을 줄지 자세히 살펴볼 것입니다.
더 나은 것을 제공 할 수 없어서 죄송합니다. 도움이 되었기를 바랍니다.
나는 A, AA, B, BA, BB 접근 방식을 전혀 권장하지 않습니다. 계층 구조를 결정하기 위해 많은 추가 처리가 필요하며 그 사이에 항목을 삽입하는 것은 전혀 재미 있지 않습니다.
OrderField, integer를 추가하기 만하면됩니다. 다음 중간 삽입에서 비표준 '단계'로 작업하거나 먼저 목록을 다시 동기화 한 다음 새 항목을 추가해야하므로 간격을 사용하지 마십시오.
0 ... N을 갖는 것은 재정렬하기 쉽고 SQL 외부에서 Array 메서드 또는 List 메서드를 사용하여 컬렉션을 전체적으로 재정렬 한 다음 각 항목을 업데이트하거나 삽입 할 위치를 파악할 수 있다면 그리고 그 전후에 각 항목에 +1 또는 -1을 입력합니다.
이를 위해 작성된 작은 라이브러리가 있으면 케이크 조각이 될 것입니다.
주문 필드를 삽입합니다. 가장 간단한 방법입니다. 고객이 필드를 재정렬 할 수 있거나 중간에 삽입해야하는 경우 해당 배치의 모든 항목에 대한 주문 필드를 다시 작성하면됩니다.
삽입 및 업데이트에 대한 성능 저하로 인해 이러한 제한이 발견되면 정수 대신 varchar 필드를 사용할 수 있습니다. 이것은 삽입 할 때 상당히 높은 수준의 정밀도를 허용합니다. 예를 들어 항목 'A'와 'B'사이에 삽입하려면 'AA'로 주문한 항목을 삽입 할 수 있습니다. 이것은 쇼핑 카트에 거의 확실히 과잉입니다.
장바구니 항목 위의 추상화 수준에서 CartOrder (CartItem과 1-n이 있음)라고 가정하면 itemOrder라는 필드를 유지할 수 있습니다.이 필드는 관련 cartItem 레코드의 쉼표로 구분 된 id (PK) 목록 일 수 있습니다. 이를 구문 분석하고 그에 따라 항목 모델을 배열해야하는 응용 프로그램 계층에 있습니다. 이 접근 방식의 큰 장점은 주문을 다시 셔플 링하는 경우 개별 개체에 대한 변경 사항이 없을 수 있지만 주문 항목 테이블 행 내에서 인덱스 필드로 주문이 유지되기 때문에 각 항목에 대해 업데이트 명령을 실행해야합니다. 인덱스 필드를 업데이트하는 행. 이 접근 방식에 대한 귀하의 비판을 알려주십시오. 이것이 어떤 방식으로 실패 할 수 있는지 알고 싶습니다.
나는 다음 과 같이 실용적으로 해결했습니다 .
순서는 UI에서 정의됩니다.
The backend gets a POST request that contains the IDs and the corresponding Position of every item in the list.
I start a transaction and update the position for every ID.
Done.
So ordering is expensive but reading the ordered list is super cheap.
I would recommend keeping gaps in the order number, so instead of 1,2,3 etc, use 10,20,30... If you need to just insert one more item, you could put it at 15, rather than reordering everything at that point.
Well, I would say the short answer is:
Create a primary key of autoidentity in the cartcontents table, then insert rows in the correct top-down order. Then by selecting from the table with order by the primary key autoidentity column would give you the same list. By doing this you have to delete all items and reinsert then in case of alterations to the cart contents. (But that is still quite a clean way of doing it) If that's not feasible, then go with the order column like suggested by others.
When I use Hibernate
, and need to save the order of a @OneToMany
, I use a Map
and not a 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 }));
In this Java example, position
is an Integer property of RuleAction
so the order is persisted that way. I guess in C# this would look rather similar.
'developer tip' 카테고리의 다른 글
WhatsApp에서 링크의 썸네일 표시 || (0) | 2020.11.11 |
---|---|
NVM을 사용하여 기본 노드 버전을 어떻게 설정할 수 있습니까? (0) | 2020.11.11 |
내 C # 프로그램의 패널 내에서 다른 응용 프로그램을 어떻게 실행할 수 있습니까? (0) | 2020.11.11 |
Java HashMap keySet () 반복 순서가 일치합니까? (0) | 2020.11.11 |
Javascript / jQuery에서 문자열의 픽셀 길이를 결정합니까? (0) | 2020.11.11 |