В Oracle, как выбрать (и назначить) строки данных, которые происходят в одну и ту же дату? - PullRequest
0 голосов
/ 14 мая 2019

Когда я пытался создать уникальный индекс в нашем конечном наборе данных, я заметил, что у нас есть данные, которые имеют несколько строк для одной и той же информации. У меня есть следующие данные. Для тех, у кого samstrat «IN», я должен классифицировать первый как «Regular», второй как «Duplicate», а третий как «Other». Другие samstrats были классифицированы правильно. Эти классификации входят в новый столбец с именем sam_type.

ROWNUM Site_id_program   smp_date   samstrat
13      1E1-134          4/21/1983  IN
14      1E1-134          4/21/1983  IN
15      1E1-134          4/21/1983  EPI
16      1E1-134          4/21/1983  IN
17      1E1-134          4/21/1983  HYP

Я пробовал следующее, но получаю ошибки, связанные с отсутствующими скобками. Но я даже не уверен, можете ли вы использовать такую ​​длинную строку кода в функции CASE или это даже наиболее практично. У нас нет никакой другой идентифицирующей информации для этих образцов, поэтому я подумал, что хочу выбрать МИНУТУ ROWNUM для Обычного, Второго в качестве Дублирующего и MAX в качестве Другого. Но я не уверен, что это возможно, так как ROWNUM, похоже, рассчитывается для каждого оператора select?

SELECT *, 
    DECODE(samstrat,'HYP','HYPO', samstrat) AS samstrat_02,
    CASE WHEN only_once='Y' THEN 'Annual'
        WHEN samstrat = 'HYP' THEN 'Other'
        WHEN samfreq = 'A' AND type = 'REG' THEN 'Annual'
        WHEN samfreq = 'A' AND type = 'DUP' THEN 'Duplicate'
        WHEN sample_no = 2 THEN 'Duplicate'
        --WHEN (MIN(ROWNUM(site_id_program ||'x'|| samstrat ||'x'|| smp_date ))) THEN 'Regular'
        --WHEN (Middle/SecondROWNUM(site_id_program ||'x'|| samstrat ||'x'|| smp_date ))) THEN 'Duplicate'
        --WHEN (MAX(ROWNUM(site_id_program ||'x'|| samstrat ||'x'|| smp_date ))) THEN 'Other'
        ELSE 'Regular'
        END AS sam_type
    FROM waterstage.wq_meltm_1982_2010_mv_test)

Я бы хотел, чтобы три рассматриваемых образца были должным образом классифицированы как обычные, дублирующие или другие. В идеале я бы не хотел создавать другое материализованное представление для этого шага.

ROWNUM Site_id_program   smp_date   samstrat  sam_type
13      1E1-134          4/21/1983  IN        Regular
14      1E1-134          4/21/1983  IN        Duplicate
15      1E1-134          4/21/1983  EPI       Regular
16      1E1-134          4/21/1983  IN        Other
17      1E1-134          4/21/1983  HYP       Other

Ответы [ 2 ]

1 голос
/ 14 мая 2019

Почему ROWNUM = 17, HYP, имеют sam_type = Other? Разве это не должно быть Regular?

Вот один из вариантов: используя аналитическую функцию ROW_NUMBER, используя разделы на site_id_program, smp_date и samstrat, решите, какой sam_type использовать. В зависимости от имеющихся у вас реальных данных это может измениться, но - это общая идея.

SQL> with test (c_rownum, site_id_program, smp_date, samstrat) as
  2    (select 13, '1E1-134', '4/21/1983', 'IN'  from dual union all
  3     select 14, '1E1-134', '4/21/1983', 'IN'  from dual union all
  4     select 15, '1E1-134', '4/21/1983', 'EPI' from dual union all
  5     select 16, '1E1-134', '4/21/1983', 'IN'  from dual union all
  6     select 17, '1E1-134', '4/21/1983', 'HYP' from dual
  7    ),
  8  inter as
  9    (select c_rownum, site_id_program, smp_date, samstrat,
 10       row_number() over (partition by site_id_program, smp_date, samstrat
 11                          order by c_rownum) rn
 12     from test
 13    )
 14  select c_rownum, site_id_program, smp_date, samstrat, rn,
 15    case when rn = 1 then 'Regular'
 16         when rn = 2 then 'Duplicate'
 17         when rn = 3 then 'Other'
 18    end sam_type
 19  from inter
 20  order by c_rownum;

  C_ROWNUM SITE_ID SMP_DATE  SAM         RN SAM_TYPE
---------- ------- --------- --- ---------- ---------
        13 1E1-134 4/21/1983 IN           1 Regular
        14 1E1-134 4/21/1983 IN           2 Duplicate
        15 1E1-134 4/21/1983 EPI          1 Regular
        16 1E1-134 4/21/1983 IN           3 Other
        17 1E1-134 4/21/1983 HYP          1 Regular

SQL>
0 голосов
/ 22 мая 2019

Получается, что ранжирование по site_id_program, smp_date, samstrat дает нам то, что нам нужно, чтобы затем выполнить соединение с исходной таблицей. В нашем операторе CASE мы теперь используем site_repeat_rank для упорядочения и последующей классификации строк данных.

CREATE materialized view wq_meltm_1982_2010_mv
AS
WITH with_sam_type AS (SELECT b.site_id_program, smp_date, samstrat, site_repeat_rank, 
       DECODE(samstrat,'HYP','HYPO', samstrat) AS samstrat_02, 
       CASE WHEN samstrat = 'S' THEN 'Blank'
            WHEN site_repeat_rank=1 AND samfreq = 'A' AND type = 'REG' THEN 'Annual'
            WHEN site_repeat_rank=1 AND only_once='Y' THEN 'Annual' 
            WHEN site_repeat_rank=1 AND samstrat = 'HYP' THEN 'Other'            
            --WHEN sample_no = 2 THEN '2ndSample' --sample_no=2 are pushed to bottom of site_repeat_rank BUT if the only record is sample_no=2 it is considered regular
            WHEN site_repeat_rank=1 THEN 'Regular' 
            WHEN site_repeat_rank=2 THEN '2ndSample'
            WHEN site_repeat_rank=3 THEN '3rdSample'
            WHEN site_repeat_rank=4 THEN '4thSample'
            WHEN site_repeat_rank=5 THEN '5thSample'
       END AS sam_type, 
       rowid_real
FROM
((SELECT a.*, rowid AS rowid_real,
       RANK () OVER (PARTITION BY site_id_program, smp_date, samstrat ORDER BY type DESC NULLS FIRST, sample_no ASC, rowid) AS site_repeat_rank
FROM waterstage.wq_meltm_1982_2010_mv_test a) b
LEFT JOIN 
(SELECT site_id_program, 'Y' AS only_once
 FROM waterstage.wq_meltm_1982_2010_mv_test
 GROUP BY site_id_program
 HAVING COUNT(site_id_program) = 1) c
ON b.site_id_program=c.site_id_program))

SELECT a.*, samstrat_02, sam_type
FROM waterstage.wq_meltm_1982_2010_mv_test a LEFT JOIN with_sam_type b
ON a.rowid=b.rowid_real;
...