【问题标题】:SELECT all EXCEPT results in a subquerySELECT all EXCEPT 结果在子查询中
【发布时间】:2016-11-01 17:00:04
【问题描述】:

我有一个查询,它连接了几个表(3 个或 4 个)并按预期得到结果。

SELECT DISTINCT test_title, stt_id FROM student_tests
LEFT JOIN student_test_answers ON sta_stt_num = stt_id 
JOIN tests ON stt_test_id = test_id
WHERE student_test_answer_id IS NULL 

我有另一个查询显示另一组数据,基本上是这样的:

    SELECT test_id, COUNT(*) AS theCount FROM tests
    JOIN test_questions ON test_id= tq_test_id
    WHERE type= 'THE_TYPE'
    GROUP BY test_id
    HAVING theCount = 1

所以基本上我不想在第一个查询中包含第二个查询的结果。 test_id 将是连接字段。

我尝试了 WHERE NOT EXISTS(-上述查询-),但没有返回不正确的结果。我也试过'不在()'

有更好的方法吗?

【问题讨论】:

  • 没有看到您的实际查询,我冒昧地猜测您的子查询不相关。
  • 请发布您的真实查询、数据样本和预期结果。您的解释不是很清楚,您的查询也不清楚:test_id= tq_test_id - 我们不知道这些列属于哪个表
  • 你是如何尝试NOT IN()的?如果您想将此查询用作子查询,则不需要结果集中的 theCount。
  • @Philipp 好吧,由于计数/分组,我无法使用它,所以我不得不放弃这个想法。
  • 是的,但是如果您想从其他结果集中排除数据,您需要计算什么?您可以保留您的having子句,但不是在别名上,而是在实际计数上(*)

标签: mysql subquery not-exists


【解决方案1】:

试试这样的:

(SELECT test_id, COUNT(*) AS theCount FROM tests
JOIN test_questions ON test_id= tq_test_id
WHERE type= 'THE_TYPE'
GROUP BY test_id
HAVING theCount = 1) outer
LEFT JOIN (
      [OtherQuery]
) a ON outer.test_id = a.test_id 
WHERE a.test_id IS NULL

【讨论】:

  • 我很确定这就是我所需要的。
  • 我不知道他的查询返回什么,但它的结构似乎工作正常。我认为上面的其他人可能也做了同样的事情。当然,我将此作为“LEFT JOIN (ANSWER)”添加到我的主查询中。以上只是我需要的相关部分。
  • @Alex 讽刺我猜?我会说其他人似乎在它和格式化上投入了更多时间。但我想我会选择对我有用的答案。社区只会投票给我所寻找的最好的。
【解决方案2】:

这是我的答案。左外连接为您提供参与者(测试)。如果 test_questions 中没有匹配项,那么它仍会返回测试行,但对于 test_questions 为 null。因此,如果您随后查找任何为空的 test_question.test_id,您将得到您要查找的内容。

我也会在你的 count 子句中具体说明,而不是为了确保 mysql 知道你真正想要计算的内容而执行 count(*)。

create database test;
use test;

create table test
(
    test_id int, 
    `the_type` varchar(20)
);

create table test_questions
(
    test_question_id int,
    test_id int,
    `the_type` varchar(20)
);

insert into test values (1, 'history');
insert into test values (2, 'chemistry');
insert into test values (3, 'reading');

insert into test_questions values (1, 1, 'hard question');
insert into test_questions values (2, 1, 'medium question');
insert into test_questions values (3, 2, 'hard question');
insert into test_questions values (4, 2, 'easy question');

select * from test;
select * from test_questions;

select t.test_id, count(distinct t.test_id)
from test t
left outer join test_questions tq on tq.test_id = t.test_id
where
    tq.test_id is null
group by
    t.test_id

【讨论】:

    【解决方案3】:

    正如评论中所写,您应该可以这样做:

    SELECT
       DISTINCT test_title,
       olc_stt_i_num 
    FROM
       student_tests  
    LEFT JOIN
       student_test_answers 
          ON olc_sta_i_stt_num = olc_stt_i_num   
    INNER JOIN
       ol_class_tests 
          ON stt_test_num = test_num  
    WHERE
       student_test_answer_id IS NULL   
    
       -- added this: replace test_id with real column 
       AND ***test_id*** NOT IN (
          SELECT
             test_id 
          FROM
             tests      
          JOIN
             test_questions 
                ON test_id= tq_test_id      
          WHERE
             type= 'THE_TYPE'      
          GROUP BY
             test_id      
          HAVING
             COUNT(*) = 1  
       )
    

    【讨论】:

    • 我只是想知道:你知道test_id 列存在于student_testsstudent_test_answersol_class_tests 中吗?我在什么地方错过了吗?
    • 不,它只是作为具有 id 的实际列的占位符,将其标记为这样。 OP暗示有这样一列,只有子查询选择中的count(*)弄乱了他的查询
    【解决方案4】:

    第二个查询到底是什么?我在这里只看到一个查询,没有子查询。此外,您的精确模式的 sqlfiddle 会有所帮助。

    无论如何,我认为您想要某种左不包括联接。它看起来像这样:

    select     test.test_id, count(*) as theCount
    from       tests test
    join       test_questions tq
    on         tq.test_id = test.test_id
    left join  tests excluded_test
    on         excluded_test.test_id = test.test_id
    where      tq.type = 'THE_TYPE'
    and        << Some condition that explains what excluded_test is >>
    and        excluded_test.test_id is null
    

    编辑:是的,原始问题肯定缺少很多细节(在某些方面已被修补),并且仍然缺失。了解示例的完整表结构在这里很重要,因此很难提供一个好的具体答案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-02-07
      • 2021-12-25
      • 1970-01-01
      • 2021-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-15
      相关资源
      最近更新 更多