繁体   English   中英

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

[英]How to get first value from first row and last value from last row in SQL Server

我在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时,应该将值设为Mysore-> Myscot

我尝试如下:

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

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

检查:

SELECT  M.FromCity [From],
        M2.ToCity [To]
FROM    #MyTable M
Inner join (select Min(ID) min ,Max(ID) max  from #MyTable M2  WHERE  M2.RequestId = 12 )
A on A.Min =ID
Inner join #MyTable M2 on M2.ID=A.Max 

输出:

在此处输入图片说明

我看到的唯一逻辑是使用表中的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]

如果使用主表中的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
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

递归版本,不取决于Id的顺序。 这个想法是要建立往返城市的最大旅行链。

WITH cte1 AS (
-- start with all trips as 1 hop chain
  SELECT [FromCity], [ToCity], 1 AS HOP 
  FROM Mytable 
  WHERE REQUESTID = 12
UNION ALL
  -- recursively add one hop if we find a trip ending in start city of the chain
  SELECT T.[FromCity], cte1.[ToCity], cte1.HOP + 1 
  FROM cte1
  JOIN Mytable t 
    ON t.[ToCity] = cte1.[FromCity]
  WHERE t.REQUESTID = 12
)
, cte2 AS (
  -- order by number of hops 
  SELECT [FromCity], [ToCity], ROW_NUMBER() OVER (ORDER BY HOP DESC) AS N
  FROM cte1
)
-- choose the chain with the more hops
SELECT [FromCity], [ToCity] 
FROM cte2 
WHERE N = 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 

试试这个代码

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM