在同一请求中使用 STRING_AGG 和 LAST_VALUE 函数
using STRING_AGG and the LAST_VALUE function in same request
如何从 id
的订单中找到的最后一条记录中获取 777777
SELECT
STRING_AGG(name,'-') WITHIN GROUP (ORDER BY id) as names,
STRING_AGG([numerToCall],'-') as calledNumbers,
--LAST_VALUE([numerToCall])) OVER (ORDER BY id) as lastCalled
'777777' as lastCalled
FROM
SimpleTest1
创建table和数据
CREATE TABLE [dbo].[simpleTest1](
[id] [int] IDENTITY(1,1) NOT NULL,
[name] [varchar](50) NOT NULL,
[numerToCall] [varchar](50) NOT NULL,
CONSTRAINT [PK_simpleTest1] PRIMARY KEY CLUSTERED
(
[id] ASC
)
) ON [PRIMARY]
SET IDENTITY_INSERT [dbo].[simpleTest1] ON
INSERT [dbo].[simpleTest1] ([id], [name], [numerToCall]) VALUES (1, N'benny', N'555555')
INSERT [dbo].[simpleTest1] ([id], [name], [numerToCall]) VALUES (2, N'helle', N'999999')
INSERT [dbo].[simpleTest1] ([id], [name], [numerToCall]) VALUES (3, N'hans', N'777777')
SET IDENTITY_INSERT [dbo].[simpleTest1] OFF
解决方案是
SELECT
STRING_AGG(t.name,'-') WITHIN GROUP (ORDER BY id) as names,
STRING_AGG(t.numerToCall, '-') as calledNumbers,
MIN(t.xxxx) as lastCalled
FROM (
SELECT *,
LAST_VALUE(t.numerToCall) OVER (ORDER BY id ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) as xxxx
from
SimpleTest1 t
) t;
感谢@Charlieface
您可以使用sub-query
SELECT
STRING_AGG(t.name,'-') WITHIN GROUP (ORDER BY id) as names,
STRING_AGG(t.[numerToCall],'-') WITHIN GROUP (ORDER BY id) as calledNumbers,
--LAST_VALUE([numerToCall])) OVER (ORDER BY id) as lastCalled
(SELECT TOP 1 InTbl.numerToCall FROM SimpleTest1 InTbl ORDER BY id desc) as lastCalled
FROM
SimpleTest1 t
GO
或者您可以解析聚合结果并从字符串中获取结果,而无需另一个查询(否 sub-query)
SELECT
STRING_AGG(t.name,'-') WITHIN GROUP (ORDER BY id) as names,
STRING_AGG(t.[numerToCall],'-') WITHIN GROUP (ORDER BY id) as calledNumbers,
--LAST_VALUE([numerToCall])) OVER (ORDER BY id) as lastCalled
RIGHT(STRING_AGG(t.[numerToCall],'-') WITHIN GROUP (ORDER BY id), CHARINDEX('-',REVERSE(STRING_AGG(t.[numerToCall],'-') WITHIN GROUP (ORDER BY id)))-1) as lastCalled
FROM
SimpleTest1 t
GO
在您的特定数据库中检查这两个解决方案并选择一个能为您提供更好性能的解决方案(SSMS 执行计划分析显示第二个查询更好但不要指望它并检查您服务器中的 IO 和 TIME)
您可以将 window 函数放在派生的 table 中,然后对其使用聚合函数(MIN
或 MAX
)
SELECT
STRING_AGG(t.name,'-') WITHIN GROUP (ORDER BY id) as names,
STRING_AGG(t.numerToCall, '-') WITHIN GROUP (ORDER BY id) as calledNumbers,
MIN(t.numerToCall]) as lastCalled
FROM (
SELECT *,
LAST_VALUE(t.numerToCall) OVER (ORDER BY id ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) as lastCalled
SimpleTest1 t
) t;
如何从 id
的订单中找到的最后一条记录中获取 777777SELECT
STRING_AGG(name,'-') WITHIN GROUP (ORDER BY id) as names,
STRING_AGG([numerToCall],'-') as calledNumbers,
--LAST_VALUE([numerToCall])) OVER (ORDER BY id) as lastCalled
'777777' as lastCalled
FROM
SimpleTest1
创建table和数据
CREATE TABLE [dbo].[simpleTest1](
[id] [int] IDENTITY(1,1) NOT NULL,
[name] [varchar](50) NOT NULL,
[numerToCall] [varchar](50) NOT NULL,
CONSTRAINT [PK_simpleTest1] PRIMARY KEY CLUSTERED
(
[id] ASC
)
) ON [PRIMARY]
SET IDENTITY_INSERT [dbo].[simpleTest1] ON
INSERT [dbo].[simpleTest1] ([id], [name], [numerToCall]) VALUES (1, N'benny', N'555555')
INSERT [dbo].[simpleTest1] ([id], [name], [numerToCall]) VALUES (2, N'helle', N'999999')
INSERT [dbo].[simpleTest1] ([id], [name], [numerToCall]) VALUES (3, N'hans', N'777777')
SET IDENTITY_INSERT [dbo].[simpleTest1] OFF
解决方案是
SELECT
STRING_AGG(t.name,'-') WITHIN GROUP (ORDER BY id) as names,
STRING_AGG(t.numerToCall, '-') as calledNumbers,
MIN(t.xxxx) as lastCalled
FROM (
SELECT *,
LAST_VALUE(t.numerToCall) OVER (ORDER BY id ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) as xxxx
from
SimpleTest1 t
) t;
感谢@Charlieface
您可以使用sub-query
SELECT
STRING_AGG(t.name,'-') WITHIN GROUP (ORDER BY id) as names,
STRING_AGG(t.[numerToCall],'-') WITHIN GROUP (ORDER BY id) as calledNumbers,
--LAST_VALUE([numerToCall])) OVER (ORDER BY id) as lastCalled
(SELECT TOP 1 InTbl.numerToCall FROM SimpleTest1 InTbl ORDER BY id desc) as lastCalled
FROM
SimpleTest1 t
GO
或者您可以解析聚合结果并从字符串中获取结果,而无需另一个查询(否 sub-query)
SELECT
STRING_AGG(t.name,'-') WITHIN GROUP (ORDER BY id) as names,
STRING_AGG(t.[numerToCall],'-') WITHIN GROUP (ORDER BY id) as calledNumbers,
--LAST_VALUE([numerToCall])) OVER (ORDER BY id) as lastCalled
RIGHT(STRING_AGG(t.[numerToCall],'-') WITHIN GROUP (ORDER BY id), CHARINDEX('-',REVERSE(STRING_AGG(t.[numerToCall],'-') WITHIN GROUP (ORDER BY id)))-1) as lastCalled
FROM
SimpleTest1 t
GO
在您的特定数据库中检查这两个解决方案并选择一个能为您提供更好性能的解决方案(SSMS 执行计划分析显示第二个查询更好但不要指望它并检查您服务器中的 IO 和 TIME)
您可以将 window 函数放在派生的 table 中,然后对其使用聚合函数(MIN
或 MAX
)
SELECT
STRING_AGG(t.name,'-') WITHIN GROUP (ORDER BY id) as names,
STRING_AGG(t.numerToCall, '-') WITHIN GROUP (ORDER BY id) as calledNumbers,
MIN(t.numerToCall]) as lastCalled
FROM (
SELECT *,
LAST_VALUE(t.numerToCall) OVER (ORDER BY id ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) as lastCalled
SimpleTest1 t
) t;