2010-06-11 3 views
0

문제 설명 : 테이블에 item_id, category_id 및 날짜 범위 (begin_date 및 end_date)가 있습니다.우선 순위가 가장 높은 멤버쉽 만 보유한 기간 범위 멤버쉽 (TRANSACT-SQL)

특정 날짜에 둘 이상의 카테고리에 속할 수있는 항목이 없습니다 (일반적으로 일일 재구성 중에 일시적으로 유효하지 않은 상태 일 수 있음).

기본적으로 모든 항목은 매일 자동으로 카테고리 (외부 데이터에서 파생 됨)에 추가되고 (제거 된 경우 다시 추가됩니다.) 해당 카테고리의 멤버십은 항목의 수명과 일치합니다 자신의 시작과 끝 날짜, 일반적으로 같은 카테고리에 전체 삶을 보내는 이유)이 일치합니다.

범주 X의 항목의 경우 기본 범주를 범주 Y에 추가하여 재정의하는 것이 바람직 할 수 있습니다. 범주 Y의 구성원 자격은 범주 X의 구성원 자격을 완전히 대체 할 수 있습니다 (즉, 범주의 구성원 자격 시작 및 종료 날짜 Y는 항목 자체의 시작 및 끝 날짜와 일치 함) 또는 임의의 시간 (시작, 중간 또는 항목 수명 만료, 여러 번 짧은 기간의 재정의)으로 임의의 기간 동안 재정의 할 수 있습니다. 카테고리 Y의 회원 자격은 자동 갱신되지 않으며 해당 카테고리에 대한 추가는 수동 데이터 입력으로 수행됩니다.

매일 카테고리 X가 다시 작성되면 중복됩니다. 여기에서 카테고리 Y의 모든 항목은 카테고리 X에도 포함됩니다 (이전에 언급 한 것처럼 금지되어 있음).

목표 : (다소 복잡하고 깨지기 쉬운 방식으로 수행되며, 이상적으로 만 남아있을 것이다) 카테고리 X의 각 다시 채우기 후, 그 저장 프로 시저를 작성하는 효율적인 방법을 찾기 위해 노력하고있어 :

종료하기 전에
  1. 이 오버랩에게

  2. 변경 기존 항목을 식별, 분류 Y로 전환 등의 항목을 카테고리 X로 시작하는 경우와 같이 (필요에 새로 추가 한 후 결국 카테고리 X로 다시 전환), 항목을 제거합니다 (항목이 전체 수명 동안 범주 Y에있는 경우). 따라서 모든 항목 r 범주 Y로 제한되지 않는 경우 범주 X 멤버십이 유지되는 동안 범주 Y (및 Y 만)로 지정됩니다.

  3. 범주 A, B, C, Z 등의 멤버쉽에는 영향을 미치지 않습니다. 우선 순위 카테고리가 있으며 완전히 다른 규칙에 따라 별도로 작성됩니다.

  4. 참고 :이 절차를 호출하기 전에 X 멤버십이 전체 항목 수명을 포함한다고 가정 할 수 있으므로이 테이블 외부의 데이터는 쿼리 할 필요가 없습니다.

  5. 보너스 크레딧 : 어떤 이유로 Y 카테고리의 동일한 항목에 인접한 또는 중복되는 멤버십이 두 개있는 경우 하나의 항목으로 함께 묶어서 표시 할 수 있지만 꼭 필요한 것은 아닙니다.

예 :

  • ITEM_ID CATEGORY_ID BEGIN_DATE 종료일
  • 1 X 20,080,101 20,090,628
  • 1 Y 20,090,101 20,090,131
  • 1 Y 20,090,601 20,090,628
  • 2 X 20,080,201 20,080,731
  • 2 Y 20080201 20080731

이 될해야 :

  • ITEM_ID CATEGORY_ID BEGIN_DATE 종료일
  • 1 X 20,080,101 20,081,231
  • 1 Y 20,090,101 20,090,131
  • 1 X 20,090,201 20,090,531
  • 1 Y 20,090,601 20,090,628
  • 에게 2 년 20080201 20080731
  • 이 중요한 경우 63,210

는,이 카테고리 X에 있어야 항목을 감안할 때 SQL Server 2005 및 SQL Server 2008

+0

카테고리 X의 인구가 복잡하고 연약하다고 말하면 카테고리 X가있는 항목을 파악하는 것입니까? 그렇지 않으면 X의 실제 날짜가 쉽습니다. 맞습니까? –

+0

바로. 나는 내가 처리하고있는 문제를 부분적으로 처리하려는 시도가 있었을 것이라고 생각한다. (특히 항목의 전체 수명이 카테고리 Y에 소비된다면 카테고리 X 멤버십을 추가하지 않으려 고 노력할 수도있다.) 그러나 그것은 부서지기 쉽다. (실제로 많은 경우에 그렇게하지는 않는 것 같습니다.) 그리고 어떤 복잡한 사례도 처리하지 못합니다. 카테고리 Y 멤버십이 수명의 맨 처음 또는 맨 마지막에있는 가장 단순한 경우조차도 아닙니다. 날짜를 변경하고 항목을 추가하거나 제거하지 마십시오. – ShadowRanger

답변

2

작업을 할 필요가, 카테고리 일단 Y 행은 당신이를 추가 할 수 있어야 이미 있습니다 X를 아래 코드와 함께 사용하십시오. 커서를 사용하거나 범주 X 행이있는 모든 항목에 대해 집합 기반 작업으로 사용하거나 다른 방식으로 사용합니다.

DECLARE 
    @y_id INT, 
    @x_id INT, 
    @item_id INT 
SELECT @y_id = category_id FROM dbo.Categories WHERE name = 'Y' 
SELECT @x_id = category_id FROM dbo.Categories WHERE name = 'X' 
SET @item_id = ??? 

;WITH Begin_Dates AS (SELECT 
    BI.item_id, 
    BI.begin_date AS begin_date 
FROM 
    Items BI 
WHERE 
    NOT EXISTS (SELECT * FROM Item_Categories BIC2 WHERE BIC2.item_id = BI.item_id AND BIC2.category_id = @y_id AND BIC2.begin_date = BI.begin_date) 
UNION 
SELECT 
    BIC1.item_id, 
    end_date AS begin_date 
FROM 
    Item_Categories BIC1 
WHERE 
    BIC1.category_id = @y_id AND 
    NOT EXISTS (SELECT * FROM dbo.Items WHERE item_id = BIC1.item_id AND BIC1.end_date = end_date)), 
End_Dates AS (SELECT 
    EI.item_id, 
    EI.end_date AS end_date 
FROM 
    Items EI 
WHERE 
    NOT EXISTS (SELECT * FROM Item_Categories EIC2 WHERE EIC2.item_id = EI.item_id AND EIC2.category_id = @y_id AND EIC2.begin_date = EI.begin_date) 
UNION 
SELECT 
    EIC1.item_id, 
    begin_date AS end_date 
FROM 
    Item_Categories EIC1 
WHERE 
    EIC1.category_id = @y_id AND 
    NOT EXISTS (SELECT * FROM dbo.Items WHERE item_id = EIC1.item_id AND EIC1.begin_date = begin_date)) 
INSERT INTO dbo.Item_Categories 
(
    item_id, 
    category_id, 
    begin_date, 
    end_date 
) 
SELECT 
    @item_id, 
    @x_id, 
    BD.begin_date, 
    ED.end_date 
FROM 
    Begin_Dates BD 
INNER JOIN End_Dates ED ON 
    ED.end_date > BD.begin_date AND 
    NOT EXISTS (SELECT * FROM End_Dates ED2 WHERE ED2.end_date > BD.begin_date AND ED2.end_date < ED.end_date) 
+0

나는이 해결책을보고있다. 문제가 있습니다 (일부는 실제 DB에서 정확하지 않은 외부 정보를 사용했기 때문에 발생합니다). 나는 내가 그것을 할 수있는 것을 볼 것이다. 고맙습니다. – ShadowRanger

+0

일단 내가하고있는 일을 알게되면 (출생 날짜를 시작일과 섞어 놓은 것이 조금 까다 롭습니다. 단순한 시나리오에서는 사실 이었지만 실제 시나리오에서는 잘못되었습니다.), 저는 제 일을 위해 일할 수있었습니다. 특정 시나리오와 하나의 세트 대신 "item_ids"세트에 적용 할 수 있습니다. 고맙습니다. – ShadowRanger

+0

작은 수정 하나 : WITH 설정에서 item_categories end_date 및 begin_date를 수정하지 않았습니다. 항목 시작일과 종료일은 변경되지 않은 상태로 사용할 수 있지만 (카테고리의 시작과 끝에있는 범주의 멤버 여야하므로) 범주 가입 날짜에 대해 동일한 작업을 수행 할 수 없으며, 재정의와 기본 카테고리 (카테고리 멤버쉽은 시작일과 종료일 모두 포함) 사이를 전환 할 때마다 하루가 중복됩니다. 각 카테고리 선택에서 "DATEADD (dy, 1, end_date) AS begin_date"및 "DATEADD (dy, -1, begin_date) AS end_date"로 변경하면 문제가 해결됩니다. – ShadowRanger