[英]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)。
我看到的唯一逻辑是使用表中的Id
并执行类似的操作。 使用CTE
您将找到每个请求的MIN
和MAX
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.