关于不同列的Where子句的SQL案例

时间:2015-05-06 11:51:13

标签: sql sql-server

我一直在尝试获取一个查询,根据给定的条件(如果isCurrent = 1或者不是),我应该根据CurriculumId /这将是一个存储过程的参数给我一个值/行。 如果isCurrent = 1,该值应返回给我具有最新StartDate的项目,但如果isCurrent = 0则应该给我一个具有最新EndDate的项目。

问题是我每个CurriculumId只需要一个项目,理想情况是isCurrent = 1和最新的StartDate(忽略剩余的行)但是,如果没有isCurrent = 1的经验,那么它应该返回到我是最新EndDate的那个。

我以前的查询几乎正常工作,但是当我想要检索一个或另一个时,我仍然得到具有最新StartDate(isCurrent = 1)的那个和具有最新EndDate的那个。

我来看看下面的问题:

SELECT table.IntProfessionalExperienceId,
    table.IsCurrent,
    table.StartDate,
    table.EndDate
FROM table
WHERE table.CurriculumId = 12
AND
CASE table.IsCurrent
WHEN 1
THEN
    table.StartDate = (
            SELECT max(table.StartDate)
            FROM table
            WHERE table.IsCurrent = 1 
            AND table.CurriculumId = 12
            GROUP BY table.CurriculumId
    )
ELSE
      table.EndDate = (
        SELECT max(table.EndDate)
        FROM table
        WHERE table.CurriculumId = 12
        GROUP BY table.CurriculumId
    )
END

单独地,查询似乎正常工作并返回假设的值,尽管当作为一个整体运行时我得到以下错误:

Msg 102, Level 15, State 1, Line 8
Incorrect syntax near '='.
Msg 102, Level 15, State 1, Line 14
Incorrect syntax near ')'.
Msg 102, Level 15, State 1, Line 21
Incorrect syntax near ')'.

我的语法错误是什么?我知道通过阅读错误查询有什么问题,但我只是不知道如何解决它。它只是语法还是我开始时查询错误?

3 个答案:

答案 0 :(得分:3)

将其拆分为多个条件,如下所示:

SELECT 
    table.IntProfessionalExperienceId,
    table.IsCurrent,
    table.StartDate,
    table.EndDate
FROM table
WHERE 
    table.CurriculumId = 12 AND
      (
        (
            Table.IsCurrent = 1 AND 
            table.StartDate = 
              (
                SELECT max(table.StartDate)
                FROM table
                WHERE 
                    table.IsCurrent = 1 AND 
                    table.CurriculumId = 12
                GROUP BY table.CurriculumId
              )
        ) OR 
        (
            ISNULL(table.IsCurrent,0) != 1 AND
            table.EndDate = 
              (
                SELECT max(table.EndDate)
                FROM table
                WHERE table.CurriculumId = 12
                GROUP BY table.CurriculumId
              )
        )
      )

编辑:另一种可以说更简单的方法是在WHERE子句中预先聚合所需的数据,这样你只需要一次调用它,而不是分别评估每一行。如下所示:

SELECT 
    table.IntProfessionalExperienceId,
    table.IsCurrent,
    table.StartDate,
    table.EndDate
FROM 
    table
     INNER JOIN 
      (
        SELECT 
            MAX(table.EndDate) AS MaxEndDate, 
            MAX(CASE WHEN table.IsCurrent = 1 THEN table.StartDate END) AS MaxCurrentStartDate
        FROM table 
        WHERE CurriculumID = 12 
      ) MaxDates ON 
        (Table.IsCurrent = 1 AND Table.StartDate = MaxDates.MaxCurrentStartDate) OR
        (ISNULL(Table.IsCurrent, 0) != 1 AND Table.EndDate = MaxDates.MaxEndDate)
WHERE 
    table.CurriculumId = 12

答案 1 :(得分:2)

使用带有适当order by子句的ROW_NUMBER为每个行在其Curriculumid组中添加一个等级。然后只取出排名为1的记录(即最佳匹配)。

select
  intprofessionalexperienceid,
  iscurrent,
  startdate,
  enddate
from
(
  select mytable.*
  row_number() over 
  (
    partition by curriculumid 
    order by 
      case when iscurrent = 1 then 1 else 2 end, 
      case when iscurrent = 1 then startdate else enddate end desc
  ) as rn
  from mytable
) ranked
where rn = 1;

(我知道这实际上并没有回答你的问题,但在我看来,这是解决问题的直接方法。)

答案 2 :(得分:1)

尝试以这种方式使用CASE州议员:

SELECT table.IntProfessionalExperienceId,
    table.IsCurrent,
    table.StartDate,
    table.EndDate
FROM table
WHERE table.CurriculumId = 12
AND table.EndDate = CASE 
                      WHEN table.IsCurrent = 1
                      THEN (
                             SELECT max(table.StartDate)
                             FROM table
                             WHERE table.IsCurrent = 1 
                             AND table.CurriculumId = 12
                             GROUP BY table.CurriculumId
                           )
                      ELSE
                           (
                             SELECT max(table.EndDate)
                             FROM table
                             WHERE table.CurriculumId = 12
                             GROUP BY table.CurriculumId
                           )
                    END