在月底不同的表之间按月和年按日期进行匹配

时间:2018-12-06 22:55:12

标签: sql oracle select

我有几个表可供选择,我只想选择每个表中相关月份的最后一天的行。这是我到目前为止所做的:

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 :(得分:1)

此查询将在您的3个表中加入每月的最新可用记录。除非您在3个表之一中有多个 same as_of_date记录,否则它不会生成重复记录。

它使用JOIN来生成表关系,并使用关联的请求动态地找到每个表中每个月的最后一条记录。

我添加了一个条件,以过滤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

答案 1 :(得分:0)

Jumm,也许这样可以更快。如果您使用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

答案 2 :(得分:0)

您可以使用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

答案 3 :(得分:0)

使用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