SQL - 2个带UNION和WITH

时间:2015-09-09 14:13:18

标签: sql sql-server

我有WITH声明(我想对我使用的结果进行一些计算)和SELECT

让我们说SELECT声明正在收集20名成绩最好的学生。

现在我想让20名学生成绩最差,所以我尝试了另一个

WITH cteGrades AS 
( 
    SELECT *
    FROM tbl_students
)
--Selecting best Grade 
SELECT TOP(20)
    cte.name, cte.surname, cte.grade
FROM 
    cteGrade cte
ORDER BY 
    cte.grade DESC

UNION

--Selecting worst Grade 
SELECT TOP(20)
    cte.name, cte.surname, cte.grade
FROM 
    cteGrades cte
ORDER BY 
    cte.grade ASC

我收到错误:

  

关键字' UNION'附近的语法不正确。

3 个答案:

答案 0 :(得分:5)

您应该删除union子句中的order by。在整个结果集上union之后进行排序。或者将查询设为cte,并对结果执行union

 WITH cteGrade AS 
          ( 
            SELECT  *
            FROM tbl_students
           )
            --Selecting best Grade 
 , top20 as 
            (SELECT TOP(20)
                 cte.name
                ,cte.surname
                ,cte.grade
            FROM cteGrade cte
            ORDER BY cte.grade DESC)
 , last20 as 
             (
            --Selecting worst Grade 
            SELECT TOP(20)
                 cte.name
                ,cte.surname
                ,cte.grade
            FROM cteGrade cte
            ORDER BY cte.grade ASC
             )
 select name, surname, grade from top20
 union all
 select name, surname, grade from last20

答案 1 :(得分:5)

WITH cteGrades AS 
( 
SELECT  *
      ,ROW_NUMBER() OVER (ORDER BY grade DESC) Best_Grades
      ,ROW_NUMBER() OVER (ORDER BY grade ASC ) Worst_Grades
FROM tbl_students
)
SELECT   cte.name
        ,cte.surname
        ,cte.grade
FROM cteGrades cte
WHERE Best_Grades  <= 20
  OR  Worst_Grades <= 20
ORDER BY cte.grade DESC

答案 2 :(得分:1)

您的原始查询只是缺少子查询周围的括号:

WITH cteGrades AS ( 
      SELECT *
      FROM tbl_students
     )
--Selecting best Grade 
(SELECT TOP(20) cte.name, cte.surname, cte.grade
 FROM cteGrade cte
 ORDER BY cte.grade DESC
) UNION
(SELECT TOP(20) cte.name, cte.surname, cte.grade
 FROM cteGrades cte
 ORDER BY cte.grade ASC
);

也可以重写使用CTE或行号,但实际上没有理由这样做。

实际上,您根本不需要CTE:

(SELECT TOP(20) s.name, s.surname, s.grade
 FROM tbl_students s
 ORDER BY s.grade DESC
) UNION
(SELECT TOP(20) s.name, s.surname, s.grade
 FROM tbl_students s
 ORDER BY s.grade ASC
);