当子查询未返回任何行时,删除WHERE条件

时间:2011-08-12 17:03:28

标签: mysql sql subquery

我正在编写一个复杂的MySQL查询,但我无法弄清楚如何完成它。

这是给我带来麻烦的部分(这只是我查询的一部分):

SELECT * FROM table AS t1
WHERE date < (
    SELECT date FROM table AS t2 
    WHERE phase="B" AND t2.target = t1.target
)

基本上,我有项目,每个项目都有日期,阶段(A,B,C)和目标。对于目标,有几个类型为A的项目,然后是类型B的单个可选项目,然后是类型为C的项目。

对于每个目标,我想在这些条件之后选择所有行:

  1. 如果有一个带有阶段“B”的项目(让我们称他为 itemX ),我想要返回日期低于 itemX <的日期的所有项目/ LI>
  2. 如果没有相位为“B”的项目,我想返回所有行
  3. 日期参数非常重要。在大多数情况下,3个阶段是不同的,不能重叠,但有些情况会发生。

    这里的问题是,我的子查询不会返回案例1中的任何行,也不会返回案例2中的单个单元格。

    如果我们在案例1中,则整个条件WHERE date < (...)无关紧要,不应在查询中应用。

    我尝试了IFNULLEXISTS的几种可能性,但我认为我做错了因为我一直遇到语法错误。

5 个答案:

答案 0 :(得分:1)

您可以尝试

SELECT * FROM table AS t1
left join 
table as t2 
on t1.Target = t2.Target
and t2.phase="B"
where t2.target is null OR 
OR t1.date < t2.Date

答案 1 :(得分:1)

也许

SELECT *
FROM table AS t1
LEFT JOIN table AS t2 ON t2.target = t1.target AND (t1.date < t2.date)
WHERE (phase = 'B')

我假设您的查询中的table实际上是两个表,而您没有进行自我加入?如果是这样,那么您必须指定您所指的哪个表格phase

答案 2 :(得分:1)

SELECT  m.*
FROM    (
        SELECT  target, MAX(date) AS maxdate
        FROM    mytable
        ) md
JOIN    mytable m
ON      m.target = md.target
        AND m.date <
        COALESCE
        (
        (
        SELECT  date
        FROM    mytable mb
        WHERE   mb.target = md.target
                AND mb.phase = 'B'
        ORDER BY
                mb.target, pmb.phase, mb.date
        LIMIT 1
        ),
        maxdate + INTERVAL 1 SECOND
        )

创建两个索引:

mytable (target, date)
mytable (target, phase, date)

让它快速工作。

答案 3 :(得分:0)

您发布的代码称为“每个条件反模式一个子查询”。使用CASE-WHEN-THEN。

答案 4 :(得分:0)

SELECT t1.*
  FROM table t1
  LEFT
  JOIN ( SELECT t.target
              , MIN(t.date) AS b_date
           FROM table t
          WHERE t.phase = 'B'
          GROUP BY t.target
       ) t2
    ON t1.target = t2.target AND t1.date < t2.b_date

如果确保给定目标的最多行数不超过一行且“阶段”=“B”,则可以不使用MIN和GROUP BY,如下所示:

SELECT t1.*
  FROM table t1
  LEFT
  JOIN ( SELECT t.target
              , t.date AS b_date
           FROM table t
          WHERE t.phase = 'B'
       ) t2
    ON t1.target = t2.target AND t1.date < t2.b_date