如何从SQL Server中的第一行获取第一个值和从最后一行获取最后一个值

时间:2018-10-04 09:58:49

标签: sql sql-server max min

我在SQL Server中有一个如下表

+---+-------------+-------------+-------------+
|Id | FromCity    | ToCity      |  RequestId  | 
+---+-------------+-------------+-------------+
| 1 | Mysore      | Atlanta     | 12          |
+---+-------------+-------------+-------------+
| 2 | Atlanta     | Singapore   | 12          |
+---+-------------+-------------+-------------+
| 3 | Singapore   | Pakistan    | 12          |
+---+-------------+-------------+-------------+
| 4 | Pakistan    | Myscot      | 12          |
+---+-------------+-------------+-------------+
| 5 | Rome        | Singapore   | 13          |
+---+-------------+-------------+-------------+

在这里,我正在尝试获取“从城市到目的地”(往返数据)的值(即Mysore-> Myscot for RequestId = 12 )。何获得此值?

当我传递RequestId = 12时,我应该获得的值为迈索尔->迈斯科特

我尝试如下:

SELECT  MIN(FromCity) [From],
        MAX(ToCity) [To]
FROM    MyTable
WHERE   RequestId = 12

但是我要到迈索尔->新加坡(基于字符串MIN和MAX)。

7 个答案:

答案 0 :(得分:2)

检查此:

BLOB
  

输出:

enter image description here

答案 1 :(得分:1)

我看到的唯一逻辑是使用表中的Id并执行类似的操作。使用CTE,您将找到每个请求的MINMAX ID,即从城市到城市。 之后,将表加入CTE以查找实际值。

declare @tbl as table
    ([Id] int, [FromCity] varchar(9), [ToCity] varchar(9), [Date Created] datetime, [RequestId] int)
;

INSERT INTO @tbl
    ([Id], [FromCity], [ToCity], [Date Created], [RequestId])
VALUES
    (1, 'Mysore', 'Atlanta', '2018-10-05 15:10:00', 12),
    (2, 'Atlanta', 'Singapore', '2018-10-06 15:10:00', 12),
    (3, 'Singapore', 'Pakistan', '2018-10-07 15:10:00', 12),
    (4, 'Pakistan', 'Myscot', '2018-10-07 15:10:00', 12),
    (5, 'UK', 'Atlanta', '2018-10-06 15:10:00', 13),
    (6, 'Atlanta', 'Singapore', '2018-10-06 15:10:00', 13),
    (7, 'Singapore', 'Italy', '2018-10-23 15:10:00', 13);


;with cte as (
    select
        MIN(Id) as [start]
        ,MAX(Id) as [end]
        ,RequestId
    from @tbl
    group by requestID
)

select
    t1.FromCity
    ,t1.[Date Created]
    ,t2.ToCity
    ,t2.[Date Created]
from cte 
inner join @tbl t1
    on t1.Id = cte.[start]
    and t1.RequestId = cte.RequestId
inner join @tbl t2
    on t2.Id = cte.[end]
    and t2.RequestId = cte.RequestId

更新:基于@Panagiotis Kanavos评论,您可以像这样简化查询

;with cte as (
    select
        MIN(Id) as [start]
        ,MAX(Id) as [end]
    from @tbl
    where RequestId = 12  ---> here you can use a variable containing the requestID
)

select
    t1.FromCity
    --,t1.[Date Created]
    ,t2.ToCity
    --,t2.[Date Created]
from cte 
inner join @tbl t1
    on t1.Id = cte.[start]
inner join @tbl t2
    on t2.Id = cte.[end]

答案 2 :(得分:1)

如果使用主表中的ID来描述旅行顺序,那么类似的方法将起作用:

SELECT startLocation.FromCity [From], endLocation.ToCity AS [To]
FROM (
SELECT MIN(Id) AS StartLocationId, MAX(Id) AS EndLocationId
FROM    MyTable
WHERE   RequestId = 12 
) AS a
INNER JOIN MyTable AS startLocation ON a.StartLocationId = startLocation.Id
INNER JOIN MyTable AS endLocation ON a.EndLocationId = endLocation.Id

这是当id只是id并且与旅行顺序不匹配时的解决方案的示例:

declare @tbl as table
    ([Id] int, [FromCity] varchar(9), [ToCity] varchar(9), [Date Created] datetime, [RequestId] int)
;

INSERT INTO @tbl
    ([Id], [FromCity], [ToCity], [Date Created], [RequestId])
VALUES
    (19, 'Mysore', 'Atlanta', '2018-10-05 15:10:00', 12),
    (22, 'Atlanta', 'Singapore', '2018-10-06 15:10:00', 12),
    (1, 'Singapore', 'Pakistan', '2018-10-07 15:10:00', 12),
    (4, 'Pakistan', 'Myscot', '2018-10-07 15:10:00', 12),
    (5, 'UK', 'Atlanta', '2018-10-06 15:10:00', 13),
    (0, 'Atlanta', 'Singapore', '2018-10-06 15:10:00', 13),
    (-1, 'Singapore', 'Italy', '2018-10-23 15:10:00', 13)
;

select * from @tbl

declare @Id int = 12
declare @FromStart nvarchar(255), @ToStart nvarchar(255) 
declare @StartResult nvarchar(255), @ToResult nvarchar(255) 
declare @StartResultFound bit = 0, @ToResultFound bit = 0

-- select random starting point
select @FromStart = [FromCity], @ToStart = [ToCity] from @tbl where [RequestId] = @Id
ORDER BY NEWID()

select @FromStart, @ToStart

while (@StartResultFound = 0)
begin
    if exists (select top 1 1 from @tbl where [RequestId] = @Id and [ToCity] = @FromStart)
    begin
        select top 1 @FromStart = [FromCity] from  @tbl where [RequestId] = @Id and [ToCity] = @FromStart
    end
    else
    begin
        set @StartResultFound = 1
        set @StartResult = @FromStart
    end
end

while (@ToResultFound = 0)
begin
    if exists (select top 1 1 from @tbl where [RequestId] = @Id and [FromCity] = @ToStart)
    begin
        select top 1 @ToStart = [ToCity] from  @tbl where [RequestId] = @Id and [FromCity] = @ToStart
    end
    else
    begin
        set @ToResultFound = 1
        set @ToResult = @ToStart
    end
end

select @StartResult, @ToResult

答案 3 :(得分:1)

SELECT  RequestId, 
        f.FromCity [From],
        t.ToCity [To]
FROM    MyTable t
    CROSS APPLY (
        SELECT TOP (1) FromCity
        FROM MyTable
        WHERE RequestId = t.RequestId
        ORDER BY Id ASC
    ) f
    CROSS APPLY (
        SELECT TOP (1) ToCity
        FROM MyTable
        WHERE RequestId = t.RequestId
        ORDER BY Id DESC
    ) t
WHERE   RequestId = 12

答案 4 :(得分:1)

递归版本,不取决于conda install -c krisvanneste kivy 的顺序。这个想法是要建立往返于城市之间的最大旅行链。

Id

答案 5 :(得分:1)

也许这是您需要的

DECLARE 
    @t TABLE (
        ID INT
    ,   FromCity VARCHAR(250)
    ,   ToCity   VARCHAR(250)
    ,   RequestId   INT 
    )

INSERT INTO @t VALUES 
 (1,'Mysore','Atlanta',12)
,(2,'Atlanta','Singapore',12)
,(3,'Singapore','Pakistan',12)
,(4,'Pakistan','Myscot',12)
,(5,'Rome','Singapore',13)


SELECT DISTINCT 
    ISNULL(FromCity, ISNULL(NextCity, PreCity) ) FromCity
,   ISNULL(ToCity, ISNULL(NextCity2, PreCity2) ) FromCity
FROM (
SELECT 
    CASE WHEN RN = 1 THEN FromCity END FromCity
,   CASE WHEN RN = CNT THEN ToCity END  ToCity
,   LEAD(CASE WHEN RN = 1 THEN FromCity END)  OVER(PARTITION BY RequestId ORDER BY ID) NextCity
,   LEAD(CASE WHEN RN = CNT THEN ToCity END)  OVER(PARTITION BY RequestId ORDER BY ID) NextCity2
,   LAG(CASE WHEN RN = 1 THEN FromCity END)  OVER(PARTITION BY RequestId ORDER BY ID) PreCity
,   LAG(CASE WHEN RN = CNT THEN ToCity END)  OVER(PARTITION BY RequestId ORDER BY ID) PreCity2
FROM (
SELECT 
*,  ROW_NUMBER() OVER(PARTITION BY RequestId ORDER BY ID) RN
,   COUNT(ToCity) OVER(PARTITION BY RequestId) CNT
FROM @t
) D
WHERE 
    RN = 1 OR RN = CNT 
) C 

答案 6 :(得分:0)

尝试此代码

SELECT MIN(Id)[从],         MAX(Id)[收件人] 从MyTable 其中RequestId = 12