选择所有具有确切字段的

时间:2018-09-18 12:34:01

标签: mysql sql laravel eloquent

我有三个表:流程文档类型文档。 Flows有许多属于文档类型的文档。

比方说,我需要选择所有具有属于某个文档类型列表的文档的流,例如,其中文档类型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 Eloquent编写查询,但这在发现正确的逻辑之后将变得微不足道。

3 个答案:

答案 0 :(得分:6)

您可以使用聚合和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)上的索引。

答案 1 :(得分:2)

基本上,使用GROUP_CONCAT,您可以获得DISTINCT document_type_id ,以获得流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' 

答案 2 :(得分:1)

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

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

这取决于您正确建立关系,并且可能取决于数据库中的唯一键,该键不允许特定流在数据透视表中附加多个文档。

通过首先计算文档数并将该计数变量(而不是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));