MySQL,如何将UNION的输出提供给WHERE子句

时间:2015-05-20 10:38:17

标签: mysql sql

我有以下SQL

SELECT tsd.ID
FROM test_series_details tsd
WHERE tsd.DIV_ID =1 
  AND tsd.END_DATE > NOW()
  AND tsd.ID NOT IN 
        ((SELECT tsr.TEST_ID
        FROM  test_series_results tsr
        WHERE tsr.STUDENT_ID=3)
    UNION 
        (SELECT tsrlv.TEST_ID
        FROM test_series_restore_log_viewer tsrlv
        WHERE tsrlv.STUDENT_ID=3
        GROUP BY tsrlv.TEST_ID))

我已经测试了以下部分查询,它正在运行,

(SELECT tsr.TEST_ID
        FROM  test_series_results tsr
        WHERE tsr.STUDENT_ID=3)
    UNION 
        (SELECT tsrlv.TEST_ID
        FROM test_series_restore_log_viewer tsrlv
        WHERE tsrlv.STUDENT_ID=3
        GROUP BY tsrlv.TEST_ID)

但是如何将此UNION的输出提供给IN条件?

错误如下

  

错误代码:1064。您的SQL语法有错误;检查   手册,对应右边的MySQL服务器版本   在&UNION附近使用的语法(SELECT tsrlv.TEST_ID FROM   test_series_restore_log_viewer tsrlv'在第9行

4 个答案:

答案 0 :(得分:2)

写这个的最好方法是两个单独的条款:

SELECT tsd.ID
FROM test_series_details tsd
WHERE tsd.DIV_ID = 1 AND
      tsd.END_DATE > NOW() AND
      tsd.ID NOT IN (SELECT tsr.TEST_ID
                     FROM test_series_results tsr
                     WHERE tsr.STUDENT_ID = 3
                    ) AND
      tsd.ID NOT IN (SELECT tsrlv.TEST_ID
                     FROM test_series_restore_log_viewer tsrlv
                     WHERE tsrlv.STUDENT_ID = 3
                    );

这允许引擎利用两个表上的索引。此外,GROUP BY不是必需的(无论是以这种方式书写还是以原始公式编写)。

对于性能 - 以防万一子查询中的ID可能是NULL - 我倾向于使用NOT EXISTS来写这个:

SELECT tsd.ID
FROM test_series_details tsd
WHERE tsd.DIV_ID = 1 AND
      tsd.END_DATE > NOW() AND
      NOT EXISTS (SELECT 1
                  FROM test_series_results tsr
                  WHERE tsr.STUDENT_ID = 3 and tsr.TEST_ID = tsd.ID
                 ) AND
      NOT EXISTS (SELECT 1
                  FROM test_series_restore_log_viewer tsrlv
                  WHERE tsrlv.STUDENT_ID = 3 and tsrlv.TEST_ID = tsd.ID
                 );

此查询的最佳索引是:test_series_results(test_id, student_id)test_series_restore_log_viewer(test_id, student_id)以及test_series_details(DIV_ID, end_date, id)

答案 1 :(得分:1)

尝试使用LEFT JOIN,如下所示

SELECT tsd.ID
FROM test_series_details tsd
LEFT JOIN ((SELECT tsr.TEST_ID
        FROM  test_series_results tsr
        WHERE tsr.STUDENT_ID=3)
        UNION 
        (SELECT tsrlv.TEST_ID
        FROM test_series_restore_log_viewer tsrlv
        WHERE tsrlv.STUDENT_ID=3
        GROUP BY tsrlv.TEST_ID)) AS T on T.TEST_ID = tsd.ID 
WHERE tsd.DIV_ID =1 
  AND tsd.END_DATE > NOW()
  AND T.TEST_ID is null

答案 2 :(得分:1)

现在怎么样 -

SELECT tsd.ID
FROM test_series_details tsd
WHERE 
tsd.DIV_ID =1 
AND tsd.END_DATE > NOW()
AND tsd.ID NOT IN (
   select TEST_ID from (
     (
        SELECT tsr.TEST_ID
        FROM  test_series_results tsr
        WHERE tsr.STUDENT_ID=3
     )
     UNION 
     (
        SELECT tsrlv.TEST_ID
        FROM test_series_restore_log_viewer tsrlv
        WHERE tsrlv.STUDENT_ID=3
        GROUP BY tsrlv.TEST_ID
     )
    )x
)

答案 3 :(得分:0)

试试这个

  SELECT tsd.ID
  FROM test_series_details tsd
  WHERE tsd.DIV_ID =1 
  AND tsd.END_DATE > NOW()
  AND tsd.ID NOT IN 
  (
      select  TEST_ID from (
       SELECT tsr.TEST_ID
       FROM  test_series_results tsr
       WHERE tsr.STUDENT_ID=3

       UNION 

       SELECT tsrlv.TEST_ID
       FROM test_series_restore_log_viewer tsrlv
       WHERE tsrlv.STUDENT_ID=3
       GROUP BY tsrlv.TEST_ID   
     )as alias 
   )