我有一个架构,其中有图像,我也有这些图像的结果。结果存在于具有不同模式的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] 删除。
我来说两句