복붙노트

[SQL] 여러 자체 조인 결과에 GROUP에 따라

SQL

여러 자체 조인 결과에 GROUP에 따라

나는 백업 어플라이언스 (Avamar를)에 ProgreSQL DB 테이블에서 백업 작업에 대한 세부 정보를 수집하려고 시도하고있다. 클라이언트 _, 데이터 세트, PLUGIN_NAME, 유형, completed_ts, STATUS_CODE, bytes_modified보다 표는 등 여러 가지 열이 있습니다. 간단한 예 :

| session_id | client_name | dataset |         plugin_name |             type |         completed_ts | status_code | bytes_modified |
|------------|-------------|---------|---------------------|------------------|----------------------|-------------|----------------|
|          1 |    server01 | Windows | Windows File System | Scheduled Backup | 2017-12-05T01:00:00Z |       30900 |       11111111 |
|          2 |    server01 | Windows | Windows File System | Scheduled Backup | 2017-12-04T01:00:00Z |       30000 |       22222222 |
|          3 |    server01 | Windows | Windows File System | Scheduled Backup | 2017-12-03T01:00:00Z |       30000 |       22222222 |
|          4 |    server01 | Windows | Windows File System | Scheduled Backup | 2017-12-02T01:00:00Z |       30000 |       22222222 |
|          5 |    server01 | Windows |         Windows VSS | Scheduled Backup | 2017-12-01T01:00:00Z |       30000 |       33333333 |
|          6 |    server02 | Windows | Windows File System | Scheduled Backup | 2017-12-05T02:00:00Z |       30000 |       44444444 |
|          7 |    server02 | Windows | Windows File System | Scheduled Backup | 2017-12-04T02:00:00Z |       30900 |       55555555 |
|          8 |    server03 | Windows | Windows File System | On-Demand Backup | 2017-12-05T03:00:00Z |       30000 |       66666666 |
|          9 |    server04 | Windows | Windows File System |         Validate | 2017-12-05T03:00:00Z |       30000 |       66666666 |

각 클라이언트 _ (서버)는 여러 데이터 집합을 가질 수 있으며, 각 데이터 세트는 여러 plugin_names을 가질 수 있습니다. 나는 시간이 지남에 "작업"활동의 목록을 얻으려면이 세 열의에 GROUP BY 수행하는 SQL 문을 만들었습니다 그래서. (http://sqlfiddle.com/#!15/f15556/1)

select
  client_name,
  dataset,
  plugin_name
from v_activities_2
where
  type like '%Backup%'
group by
  client_name, dataset, plugin_name

이러한 작업의 각 성공할 수 또는 STATUS_CODE 열을 기반으로 실패. 사용 나는 그것의 completed_ts (완료 시간)와 함께 마지막으로 좋은 백업의 결과를 얻을 수 있어요 하위 쿼리와 자체 조인 bytes_modified 더 : (http://sqlfiddle.com/#!15/f15556/16)

select
  a2.client_name,
  a2.dataset,
  a2.plugin_name,
  a2.LastGood,
  a3.status_code,
  a3.bytes_modified as LastGood_bytes
from v_activities_2 a3

join (
  select
    client_name,
    dataset,
    plugin_name,
    max(completed_ts) as LastGood
  from v_activities_2 a2
  where
    type like '%Backup%'
    and status_code in (30000,30005)   -- Successful (Good) Status codes
  group by
    client_name, dataset, plugin_name
) as a2
on a3.client_name  = a2.client_name and
   a3.dataset      = a2.dataset and
   a3.plugin_name  = a2.plugin_name and
   a3.completed_ts = a2.LastGood

http://sqlfiddle.com/#!15/f15556/3 : 나는 WHERE의 STATUS_CODE 라인을 제거하여 마지막 시도 정보를 얻기 위해 별도로 같은 일을 할 수 있습니다. 참고 대부분의 시간 LastGood 및 LastAttempted는 같은 행하지만 때때로 그들은 마지막 백업이 성공하면 따라 아니라는 것을.

내가 함께 (가능한 경우)이 두 문을 병합되는 문제가 있어요. 그래서이 결과를 얻을 것이다 :

| client_name | dataset |         plugin_name |             lastgood |  lastgood_bytes |          lastattempt | lastattempt_bytes |
|-------------|---------|---------------------|----------------------|-----------------|----------------------|-------------------|
|    server01 | Windows | Windows File System | 2017-12-04T01:00:00Z |        22222222 | 2017-12-05T01:00:00Z |          11111111 |
|    server01 | Windows |         Windows VSS | 2017-12-01T01:00:00Z |        33333333 | 2017-12-01T01:00:00Z |          33333333 |
|    server02 | Windows | Windows File System | 2017-12-05T02:00:00Z |        44444444 | 2017-12-05T02:00:00Z |          44444444 |
|    server03 | Windows | Windows File System | 2017-12-05T03:00:00Z |        66666666 | 2017-12-05T03:00:00Z |          66666666 |

난 그냥 마지막에 가입 다른 권리를 추가 (http://sqlfiddle.com/#!15/f15556/4) 및 NULL 행을 받고 시도했습니다. 일부 독서를하고 난 후에 나는 처음 두가 먼저 발생 조인 둘째 전에 임시 테이블을 만들어 실행 조인 것을 볼 수 있지만 내가 NULL 행을 얻을 수 있도록 그 시점에서 데이터 I 필요가 손실됩니다.

그루비 스크립트를 통해 PostgreSQL을 사용 8. 또한 읽기 전용 한 DB에 접근.

해결법

  1. ==============================

    1.당신은 분명히 두 개의 중간 내부에 가입 출력 테이블이 있고 공통 키로 식별 몇 가지에 대한 각에서 열을 얻을합니다. 그래서 내부 키에 그들과 합류.

    당신은 분명히 두 개의 중간 내부에 가입 출력 테이블이 있고 공통 키로 식별 몇 가지에 대한 각에서 열을 얻을합니다. 그래서 내부 키에 그들과 합류.

    select
      g.client_name,
      g.dataset,
      g.plugin_name,
      LastGood,
      g.status_code,
      LastGood_bytes
      LastAttempt,
      l.status_code,
      LastAttempt_bytes
    from
    ( -- cut & pasted Last Good http://sqlfiddle.com/#!15/f15556/16
        select
          a2.client_name,
          a2.dataset,
          a2.plugin_name,
          a2.LastGood,
          a3.status_code,
          a3.bytes_modified as LastGood_bytes
        from v_activities_2 a3
        join (
          select
            client_name,
            dataset,
            plugin_name,
            max(completed_ts) as LastGood
          from v_activities_2 a2
          where
            type like '%Backup%'
            and status_code in (30000,30005)   -- Successful (Good) Status codes
          group by
            client_name, dataset, plugin_name
        ) as a2
        on a3.client_name  = a2.client_name and
           a3.dataset      = a2.dataset and
           a3.plugin_name  = a2.plugin_name and
           a3.completed_ts = a2.LastGood
    ) as g
    join 
    ( -- cut & pasted Last Attempt http://sqlfiddle.com/#!15/f15556/3
        select
          a1.client_name,
          a1.dataset,
          a1.plugin_name,
          a1.LastAttempt,
          a3.status_code,
          a3.bytes_modified as LastAttempt_bytes
        from v_activities_2 a3
        join (
          select
            client_name,
            dataset,
            plugin_name,
            max(completed_ts) as LastAttempt
          from v_activities_2 a2
          where
            type like '%Backup%'
          group by
            client_name, dataset, plugin_name
        ) as a1
        on a3.client_name  = a1.client_name and
           a3.dataset      = a1.dataset and
           a3.plugin_name  = a1.plugin_name and
           a3.completed_ts = a1.LastAttempt
    ) as l
    on l.client_name  = g.client_name and
       l.dataset      = g.dataset and
       l.plugin_name  = g.plugin_name
    order by client_name, dataset, plugin_name
    

    이것은 좌 GROUP_BYs의 조인이의 GROUP_CONCAT에서 이상한 중복 행동에 적용 가능한 방법 중 하나를 사용합니다. 그러나 코드의 덩어리의 대응은 분명하지 않을 수 있습니다. 당신의 내면 및 GROUP_CONCAT이 최대입니다 대 그 중간이 남아 있습니다. (그러나 때문에 GROUP_CONCAT 및 그 쿼리 내역의 많은 방법이있다.)

    이 사실은 일반적으로 당신의 목적을 제공 여부 실제 사양과 제약에 따라 달라집니다. 두 조인하더라도 당신은 링크 당신이 원하는 무엇을 당신은 정확하게 당신이 "병합"무슨 뜻인지 설명 할 필요가있다. 당신은이 그룹화 된 열 값의 다른 세트가 조인 경우 당신이 원하는 말을하지 않습니다. 행이 입력에있는 내용에 따라 결과에 가서 무엇을 행 말하는 영어를 사용하는 자신을 강제로.

    PS 1 당신은 / 선언되지 않은 / 강제되지 제약 문서화했다. 가능하면 선언하십시오. 그렇지 않으면 트리거에 의해 적용합니다. 질문 텍스트 문서 코드 아니라면. 제약 조인에서 &로 그룹에 여러 subrow 값 인스턴스에 기본입니다.

    PS 2 선택하는 구문 / 의미 알아. 플러스 타의 추종을 불허 왼쪽 / 오른쪽 테이블 행이 널 (null) 확장 않습니다에 가입 whatinner - 기능 반환에 가입 무엇 오른쪽 / 왼쪽 외부 알아보세요.

    PS 3 사람이 읽을 수있는 설명에서 SQL 쿼리를 구성하는 엄지 손가락의 규칙이 있나요?

  2. ==============================

    2.여기에 또한 내 데이터 세트에 따라 가능성이 더 특정하기 위해 열심히 작동하지만 다른 방법은 다음과 같습니다 http://sqlfiddle.com/#!15/f15556/114

    여기에 또한 내 데이터 세트에 따라 가능성이 더 특정하기 위해 열심히 작동하지만 다른 방법은 다음과 같습니다 http://sqlfiddle.com/#!15/f15556/114

    select
      Actvty.client_name,
      Actvty.dataset,
      Actvty.plugin_name,
      ActvtyGood.LastGood,
      ActvtyGood.status_code as LastGood_status,
      ActvtyGood.bytes_modified as LastGood_bytes,
      ActvtyOnly.LastAttempt,
      Actvty.status_code as LastAttempt_status,
      Actvty.bytes_modified as LastAttempt_bytes
    from v_activities_2 Actvty
    
    -- 1. Get last attempt of each job (which may or may not match last good)
    join (
      select
        client_name,
        dataset,
        plugin_name,
        max(completed_ts) as LastAttempt
      from v_activities_2
      where
        type like '%Backup%'
      group by
        client_name, dataset, plugin_name
    ) as ActvtyOnly
    on Actvty.client_name  = ActvtyOnly.client_name and
       Actvty.dataset      = ActvtyOnly.dataset and
       Actvty.plugin_name  = ActvtyOnly.plugin_name and
       Actvty.completed_ts = ActvtyOnly.LastAttempt
    
    -- 4. join the list of good runs with the table of last attempts, there would never be a job that has a last good without also a last attempt.
    join (
    
      -- 3. join last good runs with the full table to get the additional details of each
      select
        ActvtyGoodSub.client_name,
        ActvtyGoodSub.dataset,
        ActvtyGoodSub.plugin_name,
        ActvtyGoodSub.LastGood,
        ActvtyAll.status_code,
        ActvtyAll.bytes_modified
      from v_activities_2 ActvtyAll
    
      -- 2. Get last Good run of each job
      join (
        select
          client_name,
          dataset,
          plugin_name,
          max(completed_ts) as LastGood
        from v_activities_2
        where
          type like '%Backup%'
          and status_code in (30000,30005)   -- Successful (Good) Status codes
        group by
          client_name, dataset, plugin_name
      ) as ActvtyGoodSub
      on ActvtyAll.client_name  = ActvtyGoodSub.client_name and
         ActvtyAll.dataset      = ActvtyGoodSub.dataset and
         ActvtyAll.plugin_name  = ActvtyGoodSub.plugin_name and
         ActvtyAll.completed_ts = ActvtyGoodSub.LastGood
    
    ) as ActvtyGood
    on Actvty.client_name  = ActvtyGood.client_name and
       Actvty.dataset      = ActvtyGood.dataset and
       Actvty.plugin_name  = ActvtyGood.plugin_name
    
  3. from https://stackoverflow.com/questions/47758492/multiple-self-join-based-on-group-by-results by cc-by-sa and MIT license