Соответствие датам по месяцам и годам в разных таблицах, где конец месяца отличается от SQL-оракула - PullRequest
0 голосов
/ 07 декабря 2018

У меня есть несколько таблиц, из которых я выбираю данные, и я хочу выбрать только строки в каждой таблице за последний день соответствующего месяца.Это то, что я сделал до сих пор:

select 
    crd.indexname,
    sum(crd.pct_weight),
    extract(year from crd.datadate) as yr, 
    extract(month from crd.datadate) as mth
from 
    ref_own.v_msci_issuer_id_map maps, 
    pm_own.esg_credit_factors msci,
    pm_own.pma_sec_attributes_hv sec,
    crd_own.ml_corp_index_data_monthly crd
where 
    maps.msci_issuer_id=msci.issuer_id
    and sec.issuer_id=maps.pimco_issuer_id
    and extract(year from msci.as_of_date)=extract(year from crd.datadate)
    and extract(year from sec.asof_date)=extract(year from crd.datadate)
    and extract(month from msci.as_of_date)=extract(month from crd.datadate)
    and extract(month from sec.asof_date)=extract(month from crd.datadate)
    and crd.isin=sec.isin
    and maps.active=1
group by 
    crd.indexname,
    extract(year from crd.datadate) ,
    extract(month from crd.datadate) 
order by 
    crd.indexname, 
    extract(year from crd.datadate) desc , 
    extract(month from crd.datadate) desc

Проблема с моим сценарием состоит в том, что есть несколько внутримесячных дней, и поэтому я получаю двойной, тройной и т. Д. Подсчет.

Ответы [ 4 ]

0 голосов
/ 07 декабря 2018

Используйте аналитическую функцию RANK, и вам не нужно использовать какие-либо коррелированные подзапросы:

SELECT indexname,
       SUM(pct_weight),
       EXTRACT(year  FROM datadate) AS yr, 
       EXTRACT(month FROM datadate) AS mth
FROM   (
  SELECT crd.indexname,
         crd.pct_weight,
         TRUNC( crd.datadate, 'MM' ) AS datadate,
         RANK() OVER (
           PARTITION BY crd.indexname, TRUNC( crd.datadate, 'MM' )
           ORDER BY TRUNC( crd.datadate, 'DD' ) DESC
         ) AS rnk
  FROM   ref_own.v_msci_issuer_id_map maps
         INNER JOIN pm_own.esg_credit_factors msci
         ON ( maps.msci_issuer_id=msci.issuer_id )
         INNER JOIN pm_own.pma_sec_attributes_hv sec
         ON ( sec.issuer_id=maps.pimco_issuer_id )
         INNER JOIN crd_own.ml_corp_index_data_monthly crd
         ON ( TRUNC( msci.as_of_date, 'MM' ) = TRUNC( crd.datadate )
              AND TRUNC( sec.asof_date, 'MM' ) = TRUNC( crd.datadate ) 
              AND crd.isin=sec.isin )
  WHERE  maps.active=1
)
WHERE  rnk = 1
GROUP BY
    indexname,
    EXTRACT(year  FROM datadate) ,
    EXTRACT(month FROM datadate) 
order by 
    indexname, 
    EXTRACT(year  FROM datadate) DESC,
    EXTRACT(month FROM datadate) DESC
0 голосов
/ 07 декабря 2018

Вы можете использовать LAST_DAY () для вычисления даты окончания каждого месяца, и я настоятельно рекомендую вам прекратить использовать запятые между именами таблиц, более 25 лет назад «явный синтаксис объединения» был формализован.

SELECT
    crd.indexname
  , extract(year from crd.datadate) as yr
  , extract(month from crd.datadate) as mth
  , COUNT( crd.ISIN )
FROM ref_own.v_msci_issuer_id_map maps
    INNER JOIN pm_own.esg_credit_factors msci ON maps.msci_issuer_id = msci.issuer_id
    INNER JOIN pm_own.pma_sec_attributes_hv sec ON sec.issuer_id = maps.pimco_issuer_id AND sec.asof_date = msci.as_of_date
    INNER JOIN crd_own.ml_corp_index_data_monthly crd ON crd.isin = sec.isin
WHERE maps.active = 1
    AND msci.as_of_date = last_day(msci.as_of_date)
GROUP BY
    crd.indexname
  , extract(year from crd.datadate)
  , extract(month from crd.datadate)
ORDER BY
    crd.indexname
  , extract(year from crd.datadate) DESC
  , extract(month from crd.datadate) DESC
0 голосов
/ 07 декабря 2018

Этот запрос объединит последнюю доступную запись за каждый месяц в ваших 3 таблицах.Он не должен генерировать дубликаты, если у вас нет нескольких записей для одного и того же as_of_date в одной из 3 таблиц.

Он использует JOIN s для генерации табличных отношений и коррелированных запросов для динамического поиска последней записи каждого месяца в каждой таблице.

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

select 
    crd.indexname,
    count(crd.ISIN),
    extract(year from crd.datadate) as yr,
    extract(month from crd.datadate) as mth
from 
    ref_own.v_msci_issuer_id_map       maps  
    join pm_own.esg_credit_factors     msci on maps.msci_issuer_id = msci.issuer_id
    join pm_own.pma_sec_attributes_hv  sec on sec.issuer_id = maps.pimco_issuer_id
    join crd_own.ml_corp_index_data_monthly crd on crd.isin = sec.isin
where 
    maps.active = 1
    and msci.as_of_date = (
        select max(as_of_date)
        from pm_own.esg_credit_factors 
        where issuer_id = msci.issuer_id and trunc(as_of_date, 'month') = trunc(crd.datadate, 'month')
    )
    and sec.as_of_date  = (
        select max(as_of_date) 
        from pm_own._own.pma_sec_attributes_hv 
        where issuer_id = sec.issuer_id and trunc(as_of_date, 'month') = trunc(crd.datadate, 'month')
    )
    and crd.as_of_date  = (
        select max(as_of_date) 
        from pm_own._own.pma_sec_attributes_hv 
        where isin = crd.isin and trunc(as_of_date, 'month') = trunc(crd.datadate, 'month')
    )
group by 
    crd.indexname,
    extract(year from crd.datadate) ,
    extract(month from crd.datadate) 
order by 
    crd.indexname, 
    extract(year from crd.datadate) desc , 
    extract(month from crd.datadate) desc
0 голосов
/ 07 декабря 2018

Джамм, может быть, так быстрее.Если вы используете group by for date вместо извлечения и использования внутреннего соединения, я думаю, ваш запрос будет быстрее и более оптимизирован.Чтобы получить последний день месяца, вы можете использовать функцию LAST_DAY (https://www.techonthenet.com/oracle/functions/last_day.php) в сочетании с вычитанием дат для получения «последнего дня месяца» и включить его в предложение where.

select crd.indexname as indexName, count(crd.ISIN) as countISIN, YEAR(crd.datadate) + '-' + MONTH(crd.datadate) as monthYear
from 
ref_own.v_msci_issuer_id_map maps INNER JOIN pm_own.esg_credit_factors msci 
ON maps.msci_issuer_id=msci.issuer_id
INNER JOIN pm_own.pma_sec_attributes_hv sec 
ON sec.issuer_id=maps.pimco_issuer_id
INNER JOIN crd_own.ml_corp_index_data_monthly crd
ON crd.isin=sec.isin
where msci.as_of_date = (SELECT MAX(as_of_date) FROM  msci group by (msci.as_of_date - LAST_DAY(crd.datadate)) LIMIT 1) 
and sec.as_of_date = (SELECT MAX(as_of_date) FROM  sec group by (msci.as_of_date - LAST_DAY(crd.datadate)) LIMIT 1) 
and maps.active=1
group by crd.indexname,crd.datadate
order by crd.indexname, crd.datadate desc
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...