仅从主表中选择子表行满足条件的行

时间:2013-08-16 22:29:21

标签: sql postgresql

在我的图像分类软件中,有表resultimage一个结果可以包含多张图片。 在image.preclassification

中,每个图像可以使用值“P”或负数“N”分类为正面

结果,其中更多图像为正IS阳性。

我想只选择积极的结果。

在阅读PostgreS文档数小时后,我找到了一个令我害怕的解决方案:

WITH tmp AS (
SELECT result.result_id AS res, image.result_id , Count( image.preclassification ) AS ImgAll,  
SUM(
CASE image.preclassification 
  WHEN 'P' THEN 1
  ELSE 0
END
) AS ImgPos

from result, image
WHERE result.result_id = image.result_id
GROUP BY result.result_id, image.result_id
)
SELECT result_id
FROM tmp
WHERE ImgPos > ImgAll/2

我的问题是,对于这种(ihmo非常常见的)问题,是否有更简单的解决方案/方法?

编辑:说明

首先,我创建一个临时表,其中包含包含正图像计数的列,并计算结果的所有图像。在下一步中,我只选择那里的行,正图像的数量大于所有图像的一半。我的第一个想法是在第一个ImgPos > ImgAll/2语句中使用WHERE而不使用WITH - 子句。但它没有像ImgPos一样工作,ImgAll被报告为未知列。

3 个答案:

答案 0 :(得分:2)

聪明的查询。但我认为你可以简化它:

select r.result_id
from result r join
     image i
     on r.result_id = i.result_id
group by r.result_id
having sum(case when i.preclassification = 'P' then 1 else 0 end) >
       sum(case when i.preclassification = 'N' then 1 else 0 end);

您也可以将其写为:

select r.*
from (select r.result_id,
             sum(case when i.preclassification = 'P' then 1 else 0 end) as NumPos,
             sum(case when i.preclassification = 'N' then 1 else 0 end) as NumNeg
      from result r join
           image i
           on r.result_id = i.result_id
      group by r.result_id
     ) r
where NumPos > NumNeg;

答案 1 :(得分:1)

我可能会做类似这两个问题的事情:

拿1:

select *
from result r
join ( select t.result_id
       from result t
       join image  i  on i.result_id = t.result_id
       group by t.result_id
       having sum(case i.preclassification when 'P' then 1 else 0 end ) >
              sum(case i.preclassification when 'N' then 1 else 0 end )
     ) s on s.result_id = r.result_id

拿2:

select r.*, p.frequence as positives , n.frequency as negatives
from result r
join      ( select t.result_id , count(*) as frequency
            from result t
            join image  i on i.result_id = r.result_id
                         and i.preclassification = 'P'
          ) p on r.result_id = p.result_id
left join ( select t.result_id , count(*) as frequency
            from result t
            join image  i on i.result_id = r.result_id
                         and i.preclassification = 'N'
          ) n on n.result_id = r.result_id
where p.frequency > coalesce( n.frequency, 0 )

在积极派生表上的内部联接是因为你必须至少有一个积极的结果为正;负面派生表上的外部联接是因为你根本不必有任何底片。

答案 2 :(得分:1)

另一种方法是 - 只是为了映射"积极"积极和消极"否定:)

select r.result_id
from result as r
    inner join image as i on r.result_id = i.result_id
group by r.result_id
having sum(case i.preclassification when 'P' then 1 when 'N' then -1 end) > 0