选择所有具有精确字段的

ffdz8vbo  于 2021-06-19  发布在  Mysql
关注(0)|答案(3)|浏览(342)

我有三个表:流、文档类型和文档。流有许多属于文档类型的文档。
假设我需要选择所有具有属于特定文档类型列表的文档的流,例如,其中文档类型id为1、2、3和4。换句话说,我只想选择具有上述所有文档类型id的文档的流。我应该如何使用逻辑/查询?
我的第一次尝试是 where in 但它不能确保文档具有所有文档类型,它至少查询一种:

select * from flows where id in (
    select flow_id from documents where document_type_id in (1, 2, 3, 4)
);

我必须用laravel雄辩地编写我的查询,但在发现正确的逻辑之后,这将是微不足道的。

2w3rbyxf

2w3rbyxf1#

您可以使用内置关系轻松添加该约束。。。

$flows = Flow::has('documents', '=', 4)->get();

这将取决于关系是否正确设置,以及数据库中的唯一键是否允许特定流在透视表中附加多个文档。
通过首先计算文档的数量并将count变量(而不是4)放到查询中,使4成为动态的可能也是明智的。
https://laravel.com/api/5.7/illuminate/database/eloquent/concerns/queriesrelationships.html#method_has
更个性化的解决方案。。。

$documentIds = [1,2,3,4];

$flows = Flow::whereHas('documents', function($q) use ($documentIds) {
    $q->whereIn('document_type_id', $documentIds);
}, '=', count($documentIds));
knsnq2tg

knsnq2tg2#

您可以使用聚合和 having :

select f.*
from flows f
where f.id in (select d.flow_id
               from documents d
               where d.document_type_id in (1, 2, 3, 4)
               group by d.flow_id
               having count(distinct d.document_type) = 4
              );

这个 = 4 保证在中找到所有四种类型 documents . 注意,我还添加了表别名和限定的所有列引用。对于您编写的任何查询,这些都是好主意。
您还可以使用相关子查询来实现这一点,在mysql中可能会更高效:

select f.*
from flows f
where exists (select 1
              from documents d
              where d.document_type_id in (1, 2, 3, 4) and
                    d.flow_id = f.id
              having count(distinct d.document_type) = 4
             );

特别是,这可以利用 documents(flow_id, document_type) .

ulmd4ohb

ulmd4ohb3#

基本上,使用组concat,你可以 DISTINCT document\u type\u id(s),用于流id,以逗号分隔的字符串连接。使用 HAVING 之后要过滤掉的子句。
下面是一个示例查询(请相应地编辑表和列名):

SELECT f.*, 
       GROUP_CONCAT(DISTINCT d.document_type_id 
                    ORDER BY d.document_type_id ASC) AS document_types_in_flow 
FROM flows AS f 
INNER JOIN documents AS d ON d.flow_id = f.id 
GROUP BY f.id 
HAVING document_types_in_flow = '1,2,3,4'

相关问题