2012-01-23 3 views
11

여기 내 질문에 대한 답을 드리겠습니다. 일련의 타임 스탬프와 기본 키로 부품 번호가있는 테이블이 있다고 가정 해 보겠습니다. 테이블은 증 분식 변경 사항을 저장합니다. 즉, 모든 타임 스탬프에 대해 필드가 변경되면 해당 변경 사항이 기록됩니다. 필드가 변경되지 않으면 새 타임 스탬프의 경우 NULL입니다. 다음은 기본적인 아이디어입니다.데이터베이스 : null이 아닌 마지막 항목을 선택하십시오.

part | timestamp | x-pos | y-pos | status 
------+-----------+-------+-------+-------- 
a5 |  151 |  5 | 15 |  g 
a5 |  153 | NULL | 17 | NULL 

(part, timestamp)이 기본 키입니다. 두 번째 레코드의 NULL은 첫 번째 레코드 이후 변경되지 않은 값을 나타냅니다.

내가 할 수있는 일은 부품으로 그룹화 된 각 필드의 최신 값을 선택하는 것입니다. 예를 들어, 위의 항목이 주어지면 결과는 부분 a5에 대해 153,5,17, g가됩니다.

현재로서는이 해킹 된 쿼리가 있습니다.

((SELECT x-pos FROM part_changes WHERE x-pos IS NOT NULL 
    ORDER BY timestamp DESC 
    LIMIT 1) 

    UNION 

    (SELECT y-pos FROM part_changesWHERE y-pos IS NOT NULL 
    ORDER BY timestamp DESC 
    LIMIT 1) 

    UNION 

    (SELECT status FROM part_changes WHERE status IS NOT NULL 
    ORDER BY timestamp DESC 
    LIMIT 1)) 

하지만 단일 열이 반환됩니다. 즉, 정리를 위해 그룹화를 사용할 수 있습니다.

창조적 인 방법으로 COALESCE 또는 IS NULL을 사용하는 것과 같은 더 우아한 방법이 있어야합니다. 그러나 나는 붙어있어 그것을 이해할 수 없다. 누구 아이디어있어?

아니요, 데이터베이스 구조를 변경할 수 없습니다.

편집 : ruakh가 올바른 생각을 가지고 있습니다. 유일한 문제는 이제 부분별로 그룹화됩니다. 여러 부분으로 그룹화하기 위해 LIMIT 1 주위를 돌고있는 것처럼 보일 수 없습니다. 어떤 아이디어?

mdahlman, 나는 postgresql의 분석 함수에 익숙하지 않습니다. 따라서이 솔루션이 복잡한 쿼리보다 쉬우면 아이디어를 게시하십시오.

편집 2 : 도움 주셔서 감사합니다. 나는 내가해야 할 일에 대해 충분히 이해하고 있다고 생각합니다.

+1

분석 함수가 허용되는지 여부를 지정해야합니다. 그들과 함께 대답은 간단해야합니다. 그들 없이는 ... 힘들어 질거야. – mdahlman

+0

거기에 얼마나 많은 null 값이 발생할 수 있습니까? 제한이 있다면 몇 가지 왼쪽 조인을 가진 해결책이 될 것입니다. 좋지는 않지만 끝낼 수 있습니다;) – rauschen

+0

한계가 있다고 생각하지 않습니다. 사실, 필드 중 하나는 NULL (대다수) (99 %와 비슷한 것)을 NULL로 가지고 있습니다. –

답변

5

UNION을 사용하는 대신 실제로 필드 목록에 하위 쿼리가 필요한 것처럼 들립니다. 즉, (SELECT ...) UNION (SELECT ...) UNION (SELECT ...) 대신 SELECT (SELECT ...), (SELECT ...), (SELECT ...)이 필요합니다. 예를 들어


:

SELECT part, 
     (SELECT x_pos 
      FROM part_changes 
      WHERE part = pc.part 
      AND x_pos IS NOT NULL 
      ORDER 
      BY timestamp DESC 
      LIMIT 1 
     ) AS x_pos, 
     (SELECT y_pos 
      FROM part_changes 
      WHERE part = pc.part 
      AND y_pos IS NOT NULL 
      ORDER 
      BY timestamp DESC 
      LIMIT 1 
     ) AS y_pos, 
     (SELECT status 
      FROM part_changes 
      WHERE part = pc.part 
      AND status IS NOT NULL 
      ORDER 
      BY timestamp DESC 
      LIMIT 1 
     ) AS status 
    FROM (SELECT DISTINCT 
       part 
      FROM part_changes 
     ) AS pc 
; 

그러나이 시점에서 정말 저장 프로 시저를 작성 고려할 것이라고

. 또한


:

SELECT DISTINCT 
     part, 
     FIRST_VALUE(x_pos) OVER 
     (PARTITION BY part 
       ORDER BY CASE WHEN x_pos IS NULL 
          THEN NULL 
          ELSE TIMESTAMP 
         END DESC NULLS LAST 
     ) AS x_pos, 
     FIRST_VALUE(y_pos) OVER 
     (PARTITION BY part 
       ORDER BY CASE WHEN y_pos IS NULL 
          THEN NULL 
          ELSE TIMESTAMP 
         END DESC NULLS LAST 
     ) AS y_pos, 
     FIRST_VALUE(status) OVER 
     (PARTITION BY part 
       ORDER BY CASE WHEN status IS NULL 
          THEN NULL 
          ELSE TIMESTAMP 
         END DESC NULLS LAST 
     ) AS status 
    FROM part_changes 
; 
+0

그 하나의 문제가 해결 된 것으로 보입니다. 감사. 그러나 부품 번호별로 그룹화하려면 '그룹 기준'이 어디로 갈지 잘 모르겠습니다. 어떤 아이디어? –

+0

@BatMasterson : 그런 종류의 세부 사항은 SQL의 사투리에 달려 있습니다. 'ORDER BY ... LIMIT 1'을 사용하여 MySQL을 목표로하고 있다고 생각합니다. 그 맞습니까? (만약 그렇다면 - 또는 질문에 태그를 편집해야합니다.) – ruakh

+0

아, 좋은 질문입니다. 이것은 postgreSQL입니다. 나는 그 소식을 업데이트 할 것이다. –

0

ruakh는 권리입니다. 대안 : SQL-CLR을 사용하여 사용자 정의 집계를 작성하십시오. 이 집계는 행의 맨 아래 맨 위를 실행하고 각 열의 최초의 널 (NULL)이 아닌 값을 기억할 수 있습니다.

응용 프로그램에서도이 작업을 수행 할 수 있습니다. 프로그램 요청 행을 정렬 된 순서 (예 : 10 행)로 배치하십시오. 위에서 설명한대로 이러한 배치를 집계하십시오. 현재 일괄 처리가 완료된 후 null 열이 있으면 다음 일괄 처리가 수행됩니다.

+0

SQL-CLR은 PostgreSQL에서 OP를 도우 려하지 않습니다. 그러나, 내장 된 것을 사용하여 수행 할 수 있으며, 정확히 무엇을 설명하는지 (PostgreSQL 위키에서 'FIRST') (http://wiki.postgresql.org/wiki/ First_%28aggregate%29). –

+0

SQL Server에 FIRST가 설치 되었으면합니다. – usr

2

부분이 인 경우이 질문에 답해야합니다.감사 ruakh

에하지만 ..이 버전처럼 해당 타임 스탬프의

SELECT 
    (SELECT timestamp FROM part_changes WHERE part = $part 
    ORDER BY timestamp DESC 
    LIMIT 1) as timestamp, 

    (SELECT x-pos FROM part_changes WHERE part = $part and x-pos IS NOT NULL 
    ORDER BY timestamp DESC 
    LIMIT 1) as xpos, 

    (SELECT y-pos FROM part_changes WHERE part = $part and y-pos IS NOT NULL 
    ORDER BY timestamp DESC 
    LIMIT 1) as ypos, 

    (SELECT status FROM part_changes WHERE part = $part and status IS NOT NULL 
    ORDER BY timestamp DESC 
    LIMIT 1)) as status 
+0

나는 각 부분에 대해 재귀 적으로 그렇게하는 것이 약간 힘들다는 것에 동의한다. – mvrak

+0

파트 번호를 인수로 사용하는 함수를 작성한 다음이 함수를 사용하면됩니다. 감사. –

1

목록 해달라고 :

select max timestamp from part_changes where x_POS is not null group by part 

당신이 볼 수 있도록 할 수 있습니다 :이 뷰 1

에게 전화를 할 수 있습니다
SELECT part_changes.part, part_changes.x-pos 
FROM part_changes left join view1 on part_changes.part = view1.part 
WHERE x-pos IS NOT NULL 
AND part_changes.timestamp = view1.timestamp 
GROUP BY part_changes.part 

어디로 가나 요? 그렇게하면 x-pos에 대한 전체 목록을 얻을 수 있습니다.

+0

흥미로운 아이디어. 내 장점으로는 특정 조인의 null-eliminating 품질을 사용하는 방법에 대해 생각했지만 어디서부터 시작해야할지 몰랐습니다. 나는 이것을 약간 실험 할 것이다. 내 유일한 관심사는 제 경우에는 실제로 더 많은 열이 있다는 것입니다. 이 게시물의 예제는 단순화 된 버전이었습니다. 너무 많은 조인이 메모리 문제가 있습니까? –

+0

당신은 몇백 명이 있다면 ... 나는 또한 그룹을 포함시키기 위해 나의 포스트를 편집했다. 이제 생각해 보면 x_pos에 대해 원하는 것을 정확히 줄 수 있다고 생각합니다. 그래도! – mvrak

+0

약 15 개의 필드 만 있고 하루에 수천 개의 레코드가 있다고 생각합니다. 나는 그것을 밖으로 시도 할 것이다. 이것은 내가 필요한 것일 수도 있습니다. –

관련 문제