SQL左联接给出重复的结果

多米尼克·布·萨姆拉(Dominic Bou-Samra)

我有一个架构,其中有图像,我也有这些图像的结果。结果存在于具有不同模式的N个表中。我需要编写一个搜索查询,该查询可以返回与某些条件(包括限制和偏移)匹配的所有图像及其结果。

一个图像可能有10个结果(2个分类,8个检测)。我希望限制作用于图像,而不是结果。因此,我希望获得1行图像的10行。

这是我到目前为止所拥有的。它的问题是结果行的复制和合并。即我希望每个结果都排成一行,并且不会像这样将检测和分类结合在一起。我需要UNION ALL还是其他?

CREATE TABLE images (
  id         VARCHAR(40)     NOT NULL,
  PRIMARY KEY (id)
);

CREATE TABLE image_results_classification (
  image_id    VARCHAR(40)          NOT NULL,
  c_confidence  REAL                 NOT NULL,
  FOREIGN KEY (image_id)  REFERENCES images(id)
);

CREATE TABLE image_results_detection (
  image_id    VARCHAR(40)          NOT NULL,
  d_confidence  REAL                 NOT NULL,
  FOREIGN KEY (image_id)  REFERENCES images(id)
);

INSERT INTO images (id) VALUES ('123');
INSERT INTO images (id) VALUES ('456');

INSERT INTO image_results_classification (image_id, c_confidence) VALUES ('123', 0.9);
INSERT INTO image_results_classification (image_id, c_confidence) VALUES ('123', 0.8);
INSERT INTO image_results_classification (image_id, c_confidence) VALUES ('456', 0.7);

INSERT INTO image_results_detection (image_id, d_confidence) VALUES ('123', 0.1);
INSERT INTO image_results_detection (image_id, d_confidence) VALUES ('123', 0.2);
INSERT INTO image_results_detection (image_id, d_confidence) VALUES ('456', 0.3);

设计该模式是为了简化此问题:两个结果表上都有更多行,而且它们之间也存在差异(不仅仅是信心)。

我想要在我的应用程序层中最终得到的是类似类型的东西:Map [Image,(List [ClassificationResult],List [DetectionResult])]

即图像,并且所有结果。具有null的结果集会很好。也许是这样的:

id   c_confidence d_confidence
123  0.9          NULL
123  0.8          NULL
123  NULL         0.1
123  NULL         0.2
456  0.7          NULL
456  NULL         0.3

这是来自DB Fiddle的查询:

SELECT *
FROM images INNER JOIN
     (SELECT id FROM images LIMIT 10 OFFSET 0
     ) AS i
     ON (images.id = i.id) OUTER LEFT JOIN 
     image_results_classification c
     ON (images.id = c.image_id) OUTER LEFT JOIN 
     image_results_detection d
     ON (images.id = d.image_id);

https://www.db-fiddle.com/f/tuDxwY7kQGfEvZSzaajESG/0

编辑:有一个辅助要求,我需要根据结果进行过滤,并能够限制和补偿图像。

我希望能够执行如下查询:

请给我所有c_confidence> 0.5的图像及其所有结果。即,如果图像的c_confidence为0.4,则应包括该图像(且不包含任何结果)。如果c_confidence为0.6,则返回所有结果(包括image_results_detection)。

我已经更新了小提琴以反映这一点:https : //www.db-fiddle.com/f/tuDxwY7kQGfEvZSzaajESG/1

在小提琴中,我不希望返回任何结果,因为该图像没有信心度> 0.8的image_results_classification

暴风雨

您可以将GROUP_CONCAT与GROUP BY一起使用。
可以在带有LIMIT的子查询中完成第一个group_concat。
为了避免这两个一对多关系之间的笛卡尔联接效应。

例如:

SELECT 
 q.*,  
 group_concat(d.d_confidence) as d_confidence_list
FROM
(
    SELECT i.id, group_concat(c.c_confidence) as c_confidence_list
    FROM images i
    LEFT JOIN image_results_classification c ON (c.image_id = i.id)
    GROUP BY i.id
    LIMIT 10
) q
LEFT JOIN image_results_detection d ON (d.image_id = q.id)
GROUP BY q.id, q.c_confidence_list

或者您可以按值使用DISTINCT,而无需子查询

SELECT 
 i.id, 
 group_concat(distinct c.c_confidence) as c_confidence_list,
 group_concat(distinct d.d_confidence) as d_confidence_list
FROM images i
LEFT JOIN image_results_classification c ON (c.image_id = i.id)
LEFT JOIN image_results_detection d ON (d.image_id = i.id)
GROUP BY i.id
LIMIT 10

但是,如果对这些联接表有很多信心,第一种方法可能会更快。

额外

这里还有2个要尝试的查询。

第一个应该得到预期的结果。
使用CTE,LIMIT仅执行一次。

with TOPIMG as (
  select * from images LIMIT 10
)
select image_id, c_confidence, null as d_confidence
from TOPIMG i
join image_results_classification c on c.image_id = i.id
union all
select image_id, null as c_confidence, d_confidence
from TOPIMG i
join image_results_detection d on d.image_id = i.id
order by image_id;

并且此查询使用技巧来以回旋方式模仿PARTITION的ROW_NUMBER函数。(我不喜欢它,它会降低性能)

with TOPIMG as (
  select * from images LIMIT 10
)
select 
image_id, 
max(case when src = 'c' then conf end) as c_conf,
max(case when src = 'd' then conf end) as d_conf
from 
(
  select image_id, 'c' as src, c_confidence as conf,
  (
    select count(*) 
    from image_results_classification c2 
    where c.image_id = c2.image_id and c.c_confidence >= c2.c_confidence
  ) as RN
  from TOPIMG i
  join image_results_classification c on (c.image_id = i.id)

  union all

  select image_id, 'd', d_confidence,
  (
    select count(*) 
    from image_results_detection d2 
    where d.image_id = d2.image_id and d.d_confidence >= d2.d_confidence
  ) as RN
  from TOPIMG i
  join image_results_detection d on (d.image_id = i.id)
) cd
group by image_id, RN
order by image_id, RN;

更新

实施特殊调味料c_confidence > 0.5要求:

with IMG as (
  select i.id as image_id, 
  max(case when c.image_id is not null then 1 else 0 end) as show_all
  from images i
  left join image_results_classification c on (c.image_id = i.id and c.c_confidence > 0.5)
  group by i.id
  order by i.id
  LIMIT 100
)
select c.image_id, 'c' as result_type, c.c_confidence as confidence
from IMG i
join image_results_classification c on c.image_id = i.image_id
where i.show_all = 1

union all

select d.image_id, 'd' as result_type, d.d_confidence as confidence
from IMG i
join image_results_detection d on d.image_id = i.image_id
where i.show_all = 1

union all

select i.image_id, null, null
from IMG i
where i.show_all = 0

order by image_id;

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章