合并两个具有不同 ORDER BY 的 SELECT 查询
Merge two SELECT queries with different ORDER BY
我有一个故事 table,我需要以下查询:
- 前 6 行按距离排序(我计算的)
- 下一行按 TIME 属性 降序
排序
declare @profileID int
set @profileID = 6
declare @longitude float
set @longitude = 17.6009169090776
declare @latitude float
set @latitude = 46.9548404806283
SELECT
first.*
FROM
(
SELECT top 6
[dbo].[Story].*,
SQRT( POWER(@Longitude - [dbo].[Story].[Longitude], 2) + POWER(@Latitude - [dbo].[Story].[Latitude], 2)) as [DistanceFromUser]
FROM
[dbo].[Follow]
LEFT JOIN
[dbo].[Story]
ON
[dbo].[Follow].[Followed] = [dbo].[Story].[ProfileID]
WHERE
[dbo].[Follow].[Follower] = @ProfileID and
[dbo].[Story].IsDraft = 0
ORDER BY
[DistanceFromUser] asc
) first
UNION ALL
SELECT
last.*
FROM
(
SELECT TOP 100 PERCENT
[dbo].[Story].*,
SQRT( POWER(@Longitude - [dbo].[Story].[Longitude], 2) + POWER(@Latitude - [dbo].[Story].[Latitude], 2)) as [DistanceFromUser]
FROM
[dbo].[Follow]
LEFT JOIN
[dbo].[Story]
ON
[dbo].[Follow].[Followed] = [dbo].[Story].[ProfileID]
WHERE
[dbo].[Follow].[Follower] = @ProfileID and
[dbo].[Story].IsDraft = 0
**ORDER BY
Time desc**
) last
我的问题是第二个查询。它不会按 TIME 属性 对第 6 行后的记录进行降序排序,而是按升序排序。
thnx
如果您希望结果集以特定方式排序,那么 最外层 SELECT
需要一个 ORDER BY
.
您可以通过在外部 ORDER BY
中包含多个键来控制排序。如果我正确读取查询,唯一的区别是 order by
,因此将查询逻辑放在 CTE 中:
WITH sf as (
SELECT s.*,
SQRT( POWER(@Longitude - s.[Longitude], 2) + POWER(@Latitude - s.[Latitude], 2)) as [DistanceFromUser]
FROM [dbo].[Follow] f LEFT JOIN
[dbo].[Story] s
ON f.[Followed] = s.[ProfileID]
WHERE f.[Follower] = @ProfileID and
s.IsDraft = 0
)
SELECT sf.*
FROM ((SELECT TOP (6) sf.*, 1 as ord
FROM sf
ORDER BY [DistanceFromUser] ASC
) UNION ALL
(SELECT TOP (6) sf.*, 2 as ord
FROM sf
ORDER BY Time DESC
)
) sf
ORDER BY ord,
(CASE WHEN ord = 1 THEN DistanceFromUser END) ASC,
(CASE WHEN ord = 2 THEN Time END) DESC;
您也可以使用 window 函数执行此操作:
WITH sf as (
SELECT s.*,
SQRT( POWER(@Longitude - s.[Longitude], 2) + POWER(@Latitude - s.[Latitude], 2)) as [DistanceFromUser]
FROM [dbo].[Follow] f LEFT JOIN
[dbo].[Story] s
ON f.[Followed] = s.[ProfileID]
WHERE f.[Follower] = @ProfileID and
s.IsDraft = 0
)
SELECT sf.*
FROM (SELECT sf.*,
ROW_NUMBER() OVER (ORDER BY DistanceFromUser) as seqnum_d,
ROW_NUMBER() OVER (ORDER BY Time DESC) as seqnum_t
FROM sf
)
) sf
WHERE seqnum_d <= 6 OR seqnum_t <= 6
ORDER BY ord,
(CASE WHEN seqnum_d <= 6 THEN DistanceFromUser END) ASC,
(CASE WHEN seqnum_t <= 6 THEN Time END) DESC;
您的版本可能包含同一行两次。对于这两种情况,此版本不会重复前 6 行。
试试这个
SELECT
first.*
FROM
(
SELECT top 6
[dbo].[Story].*,
SQRT( POWER(@Longitude - [dbo].[Story].[Longitude], 2) + POWER(@Latitude - [dbo].[Story].[Latitude], 2)) as [DistanceFromUser]
,1 as ord
FROM
[dbo].[Follow]
LEFT JOIN
[dbo].[Story]
ON
[dbo].[Follow].[Followed] = [dbo].[Story].[ProfileID]
WHERE
[dbo].[Follow].[Follower] = @ProfileID and
[dbo].[Story].IsDraft = 0
ORDER BY
[DistanceFromUser] asc
) first
UNION ALL
SELECT
last.*
FROM
(
SELECT TOP 100 PERCENT
[dbo].[Story].*,
SQRT( POWER(@Longitude - [dbo].[Story].[Longitude], 2) + POWER(@Latitude - [dbo].[Story].[Latitude], 2)) as [DistanceFromUser]
,row_number() over(order by Time desc) as ord
FROM
[dbo].[Follow]
LEFT JOIN
[dbo].[Story]
ON
[dbo].[Follow].[Followed] = [dbo].[Story].[ProfileID]
WHERE
[dbo].[Follow].[Follower] = @ProfileID and
[dbo].[Story].IsDraft = 0
**ORDER BY
Time desc**
) last
我的尝试(例子)
declare @ta as table
(
id int
,na varchar(100)
,sal numeric(18,2)
)
insert into @ta( id,na,sal) values (1,'aa',10)
insert into @ta( id,na,sal) values (3,'bb',100)
insert into @ta( id,na,sal) values (2,'c',5)
insert into @ta( id,na,sal) values (4,'dd',50)
select * from
(select top 2 * , 1 as ord from @ta order by id) as f
union all
select * from (select top 100 percent * , row_number() over(order by sal desc) ord from @ta order by sal desc
) as tt
所以我以下一个解决方案结束,感谢大家
WITH TempTable as
(
SELECT [dbo].[Story].*,
SQRT( POWER(@Longitude - [dbo].[Story].[Longitude], 2) + POWER(@Latitude - [dbo].[Story].[Latitude], 2)) as [DistanceFromUser]
FROM
[dbo].[Follow]
LEFT JOIN
[dbo].[Story]
ON [dbo].[Follow].[Followed] = [dbo].[Story].[ProfileID]
WHERE [dbo].[Follow].[Follower] = @ProfileID and
[dbo].[Story].IsDraft = 0
)
SELECT
first.*
FROM
(
SELECT top 6
*,
1 as ord
FROM
TempTable
ORDER BY
[DistanceFromUser] asc
) first
UNION ALL
SELECT
last.*
FROM
(
SELECT TOP 100 PERCENT
*,
row_number() over(order by Time desc) as ord
FROM
TempTable
ORDER BY
Time desc
) last
我有一个故事 table,我需要以下查询: - 前 6 行按距离排序(我计算的) - 下一行按 TIME 属性 降序
排序declare @profileID int
set @profileID = 6
declare @longitude float
set @longitude = 17.6009169090776
declare @latitude float
set @latitude = 46.9548404806283
SELECT
first.*
FROM
(
SELECT top 6
[dbo].[Story].*,
SQRT( POWER(@Longitude - [dbo].[Story].[Longitude], 2) + POWER(@Latitude - [dbo].[Story].[Latitude], 2)) as [DistanceFromUser]
FROM
[dbo].[Follow]
LEFT JOIN
[dbo].[Story]
ON
[dbo].[Follow].[Followed] = [dbo].[Story].[ProfileID]
WHERE
[dbo].[Follow].[Follower] = @ProfileID and
[dbo].[Story].IsDraft = 0
ORDER BY
[DistanceFromUser] asc
) first
UNION ALL
SELECT
last.*
FROM
(
SELECT TOP 100 PERCENT
[dbo].[Story].*,
SQRT( POWER(@Longitude - [dbo].[Story].[Longitude], 2) + POWER(@Latitude - [dbo].[Story].[Latitude], 2)) as [DistanceFromUser]
FROM
[dbo].[Follow]
LEFT JOIN
[dbo].[Story]
ON
[dbo].[Follow].[Followed] = [dbo].[Story].[ProfileID]
WHERE
[dbo].[Follow].[Follower] = @ProfileID and
[dbo].[Story].IsDraft = 0
**ORDER BY
Time desc**
) last
我的问题是第二个查询。它不会按 TIME 属性 对第 6 行后的记录进行降序排序,而是按升序排序。
thnx
如果您希望结果集以特定方式排序,那么 最外层 SELECT
需要一个 ORDER BY
.
您可以通过在外部 ORDER BY
中包含多个键来控制排序。如果我正确读取查询,唯一的区别是 order by
,因此将查询逻辑放在 CTE 中:
WITH sf as (
SELECT s.*,
SQRT( POWER(@Longitude - s.[Longitude], 2) + POWER(@Latitude - s.[Latitude], 2)) as [DistanceFromUser]
FROM [dbo].[Follow] f LEFT JOIN
[dbo].[Story] s
ON f.[Followed] = s.[ProfileID]
WHERE f.[Follower] = @ProfileID and
s.IsDraft = 0
)
SELECT sf.*
FROM ((SELECT TOP (6) sf.*, 1 as ord
FROM sf
ORDER BY [DistanceFromUser] ASC
) UNION ALL
(SELECT TOP (6) sf.*, 2 as ord
FROM sf
ORDER BY Time DESC
)
) sf
ORDER BY ord,
(CASE WHEN ord = 1 THEN DistanceFromUser END) ASC,
(CASE WHEN ord = 2 THEN Time END) DESC;
您也可以使用 window 函数执行此操作:
WITH sf as (
SELECT s.*,
SQRT( POWER(@Longitude - s.[Longitude], 2) + POWER(@Latitude - s.[Latitude], 2)) as [DistanceFromUser]
FROM [dbo].[Follow] f LEFT JOIN
[dbo].[Story] s
ON f.[Followed] = s.[ProfileID]
WHERE f.[Follower] = @ProfileID and
s.IsDraft = 0
)
SELECT sf.*
FROM (SELECT sf.*,
ROW_NUMBER() OVER (ORDER BY DistanceFromUser) as seqnum_d,
ROW_NUMBER() OVER (ORDER BY Time DESC) as seqnum_t
FROM sf
)
) sf
WHERE seqnum_d <= 6 OR seqnum_t <= 6
ORDER BY ord,
(CASE WHEN seqnum_d <= 6 THEN DistanceFromUser END) ASC,
(CASE WHEN seqnum_t <= 6 THEN Time END) DESC;
您的版本可能包含同一行两次。对于这两种情况,此版本不会重复前 6 行。
试试这个
SELECT
first.*
FROM
(
SELECT top 6
[dbo].[Story].*,
SQRT( POWER(@Longitude - [dbo].[Story].[Longitude], 2) + POWER(@Latitude - [dbo].[Story].[Latitude], 2)) as [DistanceFromUser]
,1 as ord
FROM
[dbo].[Follow]
LEFT JOIN
[dbo].[Story]
ON
[dbo].[Follow].[Followed] = [dbo].[Story].[ProfileID]
WHERE
[dbo].[Follow].[Follower] = @ProfileID and
[dbo].[Story].IsDraft = 0
ORDER BY
[DistanceFromUser] asc
) first
UNION ALL
SELECT
last.*
FROM
(
SELECT TOP 100 PERCENT
[dbo].[Story].*,
SQRT( POWER(@Longitude - [dbo].[Story].[Longitude], 2) + POWER(@Latitude - [dbo].[Story].[Latitude], 2)) as [DistanceFromUser]
,row_number() over(order by Time desc) as ord
FROM
[dbo].[Follow]
LEFT JOIN
[dbo].[Story]
ON
[dbo].[Follow].[Followed] = [dbo].[Story].[ProfileID]
WHERE
[dbo].[Follow].[Follower] = @ProfileID and
[dbo].[Story].IsDraft = 0
**ORDER BY
Time desc**
) last
我的尝试(例子)
declare @ta as table
(
id int
,na varchar(100)
,sal numeric(18,2)
)
insert into @ta( id,na,sal) values (1,'aa',10)
insert into @ta( id,na,sal) values (3,'bb',100)
insert into @ta( id,na,sal) values (2,'c',5)
insert into @ta( id,na,sal) values (4,'dd',50)
select * from
(select top 2 * , 1 as ord from @ta order by id) as f
union all
select * from (select top 100 percent * , row_number() over(order by sal desc) ord from @ta order by sal desc
) as tt
所以我以下一个解决方案结束,感谢大家
WITH TempTable as
(
SELECT [dbo].[Story].*,
SQRT( POWER(@Longitude - [dbo].[Story].[Longitude], 2) + POWER(@Latitude - [dbo].[Story].[Latitude], 2)) as [DistanceFromUser]
FROM
[dbo].[Follow]
LEFT JOIN
[dbo].[Story]
ON [dbo].[Follow].[Followed] = [dbo].[Story].[ProfileID]
WHERE [dbo].[Follow].[Follower] = @ProfileID and
[dbo].[Story].IsDraft = 0
)
SELECT
first.*
FROM
(
SELECT top 6
*,
1 as ord
FROM
TempTable
ORDER BY
[DistanceFromUser] asc
) first
UNION ALL
SELECT
last.*
FROM
(
SELECT TOP 100 PERCENT
*,
row_number() over(order by Time desc) as ord
FROM
TempTable
ORDER BY
Time desc
) last