迭代表中的组

时间:2017-06-23 09:59:31

标签: sql postgresql postgresql-9.4

我有以下数据:

cte1
===========================
m_ids    |p_id       |level
---------|-----------|-----
{123}    |98         |1
{123}    |111        |2
{432,222}|215        |1
{432,222}|215        |1
{432,222}|240        |2
{432,222}|240        |2
{432,222}|437        |3
{432,222}|275        |3

我必须执行以下操作:

  1. 通过以下算法提取p_id

    1. 对于具有相同m_ids
    2. 的每一行
    3. 每组:
      2.I.按p_id分组记录 2.II.按level订购desc记录 2.III。选择p_id,其精确计数为m_ids长度,最大level
  2. 到目前为止,我没有完全编写这个算法,但我写了(可能是错误的,我得到array_length)这个在最后一部分:

    SELECT id 
    FROM   grouped_cte1 
    GROUP  BY id, 
              level 
    HAVING Count(*) = array_length(grouped_cte1.m_ids, 1) 
    ORDER  BY level DESC 
    LIMIT  1 
    

    grouped_cte1的{​​{1}}是

    m_ids={123}

    m_ids |p_id |level ---------|-----------|----- {123} |98 |1 {123} |111 |2

    m_ids={432,222}

    2)将来自p.1的查询与以下内容相结合。以下为每个m_ids |p_id |level ---------|-----------|----- {432,222}|215 |1 {432,222}|215 |1 {432,222}|240 |2 {432,222}|240 |2 {432,222}|437 |3 {432,222}|275 |3 {/ 1}} p_id提取level=1

    m_ids

    导致以下结果:

    select m_ids, p_id from cte1 where level=1 --also selecting m_ids for joining later`
    

    理想的结果:

    m_ids    |p_id
    ---------|----
    {123}    |98  
    {432,222}|215   
    

    所以有人可以帮我解决算法的第一部分(可选)将它与第二部分组合在一个查询中吗?

    编辑:到目前为止我失败了:
    1.在迭代时将m_ids |result_1 |result_2 ---------|-----------|-------- {123} |111 |98 {432,222}|240 |215 的表格分解为子表格 2.对查询中的相应行执行m_ids的计算。

1 个答案:

答案 0 :(得分:1)

对于查询的第一部分,您处于正确的轨道上,但是您需要更改分组逻辑,然后再次加入表格,按照每个m_ids的最高级别对其进行过滤,您可以使用{{1 }}子句与适当的排序相结合:

DISTINCT ON

这会给你:

select 
  distinct on (t.m_ids)
  t.m_ids, t.p_id, t.level
from cte1 t
join (
  select
    m_ids,
    p_id
  from cte1
  group by m_ids, p_id
  having count(*) = array_length(m_ids, 1)
  ) as g using (m_ids, p_id)
order by t.m_ids, t.level DESC;

然后当与第二个查询结合使用时(使用 m_ids | p_id | level -----------+------+------- {123} | 111 | 2 {432,222} | 240 | 2 进行显示,当第一个查询缺少这样的条件时)我通过添加distinct来修改,因为可以(实际上是)多个记录对于FULL JOIN对第一级,它看起来像:

m_ids, p_id

给你结果:

select 
  coalesce(r1.m_ids, r2.m_ids) as m_ids,
  r1.p_id AS result_1,
  r2.p_id AS result_2
from (
  select 
    distinct on (t.m_ids)
    t.m_ids, t.p_id, t.level
  from cte1 t
  join (
    select
      m_ids,
      p_id
    from cte1
    group by m_ids, p_id
    having count(*) = array_length(m_ids, 1)
    ) as g using (m_ids, p_id)
  order by t.m_ids, t.level DESC
  ) r1
full join (
  select distinct m_ids, p_id
  from cte1
  where level = 1
  ) r2 on r1.m_ids = r2.m_ids

看起来与你的预期不同,但从我对逻辑的理解是正确的。如果我误解了什么,请告诉我。

仅仅为了逻辑解释,有一点:

为什么{123}的m_ids为result_1返回111?

  • 对于 m_ids | result_1 | result_2 -----------+----------+---------- {123} | 111 | 98 {432,222} | 240 | 215 组,我们有两个不同的m_ids = {123}
  • p_id98都考虑了111长度
  • 的平等计数条件
  • m_ids具有更高级别,因此被选为result_1