PostgreSQL - 计算售出机构的数量

PostgreSQL - Calculating number of institutions that sold counts

我们有一个叫 'holdings' 的 table。 包含各季度金融机构持股数量信息。

其中有以下列:

institution_id symbol shares quarter
1 AAPL 0 2020_Q4
2 TSLA 200000 2020_Q4
1 AAPL 100000 2020_Q3

我们要计算编号。在特定季度出售了特定公司(用符号表示)的持股的机构的数量。 我们目前有这样的查询,但我认为它可以改进。

select count(*) as "soldCount",sum(q3.shares) as "soldShares" from 
        (select * from holdings 
         where quarter='2020_Q3'
        and symbol='AAPL') q3
        left join (select * from holdings 
         where quarter='2020_Q4'
        and symbol='AAPL') q4
        on q3.institution_id=q4.institution_id
        where 
         q3.shares>0 
        and (q4.shares=0 or q4.shares is null)

附加信息: Table 'holdings' 被 'quarter' 分割。 指数是在 'institution_id'、'symbol' 和 'quarter' 上创建的。 列的组合(institution_id、符号、四分之一)是唯一的。

非常感谢任何帮助。 提前致谢。

您必须使用 window 函数引导以下方式:

select * from (
  select 
      holdings.*,
      -- use lead for retrieve previous quarter shares 
      lead(shares) over (partition by institution_id, symbol order by quarter desc) previous_quarter
  from holdings
  where symbol = 'AAPL'
) copmarsion 
-- limit records where shares less when previous_quarter
where shares < coalesce(previous_quarter, 0);

PostgeSQL fiddle

SELECT COUNT(*) AS "soldCount",SUM(T1.shares) as "soldShares" FROM holdings T1
LEFT JOIN holdings T2 ON T1.institution_id = T2.institution_id
WHERE (T1.quarter = '2020_Q3' AND T1.symbol = 'AAPL') OR (T2.quarter = '2020_Q4' AND T2.symbol = 'AAPL')
AND T1.shares > 0  AND (T2.shares = 0 OR T2.shares IS NULL)

通常 EXISTSLEFT 连接执行得更好:

SELECT COUNT(*) AS "soldCount",
       SUM(q3.shares) AS "soldShares" 
FROM holdings q3
WHERE q3.quarter='2020_Q3' AND q3.symbol='AAPL' AND q3.shares>0
  AND NOT EXISTS (
    SELECT 1 
    FROM holdings q4 
    WHERE q4.institution_id=q3.institution_id
      AND q4.quarter='2020_Q4' AND q4.symbol='AAPL'
      AND q4.shares<>0
  )

我只会使用聚合。自己获取机构:

select symbol, institution, sum(shares) as q3_shares
from hodings
where quarter in ('2020_Q3', '2020_Q4') and
      symbol = 'AAPL'
group by symbol, institution
having sum(shares) filter (where quarter = '2020_Q3') = sum(shares) and
       sum(shares) > 0;

having 子句的逻辑是:“所有份额都在'2020_Q3'中并且至少有一个份额”。

然后如果你想要总数,第二级聚合:

select symbol, count(*), sum(q3_shares)
from (select symbol, institution, sum(shares) as q3_shares
      from hodings
      where quarter in ('2020_Q3', '2020_Q4') and
            symbol = 'AAPL'
      group by symbol, institution
      having sum(shares) filter (where quarter = '2020_Q3') = sum(shares) and
             sum(shares) > 0
     ) si;