SQL Server Sort on T-SQL unioned query with CTE

eivgtgni  于 2023-10-15  发布在  其他
关注(0)|答案(3)|浏览(94)

I need to do a sort on a T-SQL unioned query. No matter how I write the query, I'm getting a syntax error once I introduce the ORDER BY clause.
Incorrect syntax near the keyword 'order'

T-SQL query

WITH s1
AS (select '1' as id
    union
    select '4' as id
    union
    select '2' as id
    union
    select '3' as id
    union
    select '5' as id
   ),
     s2
AS (select '4' as id,
           100 as val
    union
    select '1' as id,
           500 as val
    union
    select '3' as id,
           700 as val
    union
    select '2' as id,
           800 as val
   )
(select '9' as id,
        700 as val) -- id 9 should stay on first row
UNION
(select s1.id,
        s2.val
 from s1
     Left join s2
         on s1.id = s2.id  --Order by s2.val causing a syntax error )

Query output

idval
1500
2800
3700
4100
5NULL
9700

Desired output

idval
9700
4100
1500
3700
2800
5NULL
1szpjjfi

1szpjjfi1#

Add an additional column specially for ordered, but don't select it e.g.

SELECT id, val
FROM (
  SELECT '9' AS id, 700 AS val, 1 AS SortOrder
  UNION ALL -- Always use union all where you can for performance
  SELECT s1.id, s2.val, 0 AS SortOrder
  FROM s1
  LEFT JOIN s2 ON s1.id = s2.id
) x
ORDER BY SortOrder DESC, val
mftmpeh8

mftmpeh82#

Your end part should be like this for desired output.

UNION all
select *
from (
select top 100 percent s1.id,
    s2.val
from s1
 Left join s2
     on s1.id = s2.id  
order by val
) sub_query

Edit: TOP 100 percent doesn't work in newer versions. (TOP [hard coded value]) will work but it would not be a clean solution).

wmtdaxz3

wmtdaxz33#

The order by clause needs to be applied to the final select . You can use a subquery to perform the union and then select the results of the subquery and order them. A case expression in the order by clause will force the '9' row to the top of the results.

WITH
  s1 AS ( select id from ( values ( '1' ), ( '4' ), ( '2' ), ( '3' ), ( '5' ) ) as s1v( id ) ),
  s2 AS ( select id, val from ( values ( '4', 100 ), ( '1', 500 ), ( '3', 700 ), ( '2', 800 ) ) as s2v( id, val ) )
select id, val
  from (
    select '9' as id, 700 as val -- id 9 should stay on first row
    union
    select s1.id, s2.val
      from s1 left join s2 on s1.id = s2.id
    ) as Antoine
  order by case when id = '9' then 0 else 1 end, -- Force '9' to be the first row.
    val;

dbfiddle .

相关问题