mariadb 如何仅获取应用此WHERE子句的所有行?

xzabzqsa  于 2022-11-08  发布在  其他
关注(0)|答案(4)|浏览(130)

我有两个表,任务视图,结构如下:

  • 责任
  • --识别码
  • --状态
  • 检视
  • --识别码
  • -- taskid(位于www.example.com的FKtasks.id)
  • --状态

任务表有一行id = 1,状态= 1,而视图表有两行id = 1,taskid = 1,状态= 1和id = 2,taskid = 1,状态= 0。
当我试图获取所有视图状态都设置为1的所有任务id,并且任务本身的状态也设置为1,然后我返回一行,任务id = 1,因为视图编号1设置为1,视图编号2设置为0。
因此,基本上,我需要的是一个SQL语句,它只为每个任务返回一行,该任务的所有视图和任务状态都设置为1(tasks.status = 1,views.status = 1),并且只有在这种情况发生时,如果任何任务的视图设置为不同于1的值,则SQL语句不会返回它。
这是我的SQL语句到目前为止,哪种工作,但仍有一些我错过了,因为它没有工作的预期。对不起,如果有些不清楚!

SELECT tasks.id FROM tasks JOIN views ON tasks.id = views.taskid WHERE tasks.status = 1 AND views.status = 1;
bd1hkmkf

bd1hkmkf1#

tasks联接到使用聚合的查询,以便仅返回min status设置为1(这意味着没有0)的taskid

SELECT t.id 
FROM tasks t 
INNER JOIN (
  SELECT taskid
  FROM views 
  GROUP BY taskid
  HAVING MIN(status) = 1
) v ON v.taskid = t.id
WHERE t.status = 1;
dba5bblo

dba5bblo2#

with t as (select taskid,
 count(status) status_cnt,
 sum(case when status = 1 then 1 else 0 end) as status_1_cnt
 from views 
 group by taskid),
t2 as (select taskid from t where status_1_cnt > 0 and status_cnt = status_1_cnt)
select tasks.id from tasks join t2 on tasks.id = t2.taskid and status = 1

因此,如果我没有看错你的问题,你希望视图中的所有状态都是每个taskid为1。因此,我将对视图状态进行计数,并将其与视图状态为1的情况进行比较。(case语句)。
则只需将其连接到任务状态为1的任务表
(虽然我更喜欢@forpas的回答)

4uqofj5v

4uqofj5v3#

从概念上讲,您只希望联接视图表中status = 1的记录,因此如下所示:

SELECT A.id
FROM
    tasks A
    INNER JOIN
    (
        SELECT
            tasks.taskid 
        FROM
            views 
        WHERE
            view.status = 1
    ) B
    ON A.id = B.taskid

虽然语法不太直观,但它是等效的,而且更短:

SELECT 
    tasks.id
FROM 
    tasks 
    JOIN views
    ON tasks.id = views.taskid
    AND view.status = 1
WHERE
    tasks.status = 1

这也应该起作用,因为一个不同的原因(更像是一个技巧):

SELECT A.id
FROM
    tasks A
    INNER JOIN views B
    ON a.id = b.taskid
    and a.status = b.status
WHERE
    A.status = 1

如果这是您所需要的(视图中的匹配记录要求视图中不存在状态为0的其他记录),这可能是一个更严格的测试-但是如果表的大小很大,我希望避免在现实生活中使用相关子查询的这种风格:

SELECT A.id
FROM
    tasks A
    INNER JOIN views B
    ON A.id = B.taskid
WHERE
    A.status = 1
    AND B.status = 1
    AND NOT EXISTS (SELECT * FROM views c 
                     WHERE c.taskid = b.taskid and c.status = 0)

最后,这是一个从概念上更多地考虑集合交集的解决方案:

SELECT A.id
FROM
    tasks a
    INNER JOIN views a
    ON A.id = b.taskid
    AND b.status = 1
    LEFT JOIN views c
    ON a.id = c.taskid
    AND c.status = 0
WHERE
    A.status = 1
    AND c.status is null

我刚刚看到forpas刚刚展示了一个不同的但非常好的解决方案,使用带有min()子句的聚合从视图中只选择适当的记录用于加入任务,这对我来说似乎是赢家:)

tjrkku2a

tjrkku2a4#

如果我没理解错的话,你想得到任务的id,当且仅当它的status = 1,并且views表中有特定的记录,只有相同的status = 1
则您的查询将如下所示:

select tasks.id 
from tasks 
where status =1 and not exists(
    select 1 
    from views 
    where  taskid=tasks.id and views.status!=tasks.status)

检查演示https://www.db-fiddle.com/f/cQfQMx5LGJN516ND2iVj8y/3

相关问题