SQL - 选择两个字符串行之间的所有行
Posted
技术标签:
【中文标题】SQL - 选择两个字符串行之间的所有行【英文标题】:SQL - Select all rows between two string rows 【发布时间】:2015-04-19 21:36:25 【问题描述】:是否可以返回匹配行之间的所有行?
我正在尝试查询一个审计表,作业在其中写入审计表。有明确的开始审计消息和结束审计消息以及它们之间的信息。是否可以让一个 select 语句返回“开始”审计条目和“结束”条目之间的所有行?
数据示例。
DATE TIME USER ENTRY
----------------------- -------- -------------------- --------------------------------------------------------------------
2015-04-13 07:30:15.150 07:30:15 CmdLne SOME JOB STARTED FOR PROCESSING DATE 13/04/2015
2015-04-13 07:31:15.150 07:31:15 CmdLne PROCESSED 10 WHATEVERS
2015-04-13 07:32:25.150 07:32:25 CmdLne PROCESSED 10 SOMETHINGS
2015-04-13 07:33:33.150 07:33:33 CmdLne PROCESSED 40 XYZ
2015-04-13 07:33:34.150 07:33:34 CmdLne SOME JOB FINISHED FOR PROCESSING DATE 13/04/2015
因为不知道在审计写入期间会有多少审计条目,它必须能够选择“开始”条目和“结束”条目之间的所有内容。这可能吗?
【问题讨论】:
你知道非开始行的开始/结束入口还是入口代码?? 是否存在重叠的审计事件,即用户 Fred 和 Wilma 所做的工作是否会导致审计表同时包含他们俩的记录? 单个用户是否会导致重叠的审计事件,例如长期运行的报告和导入新数据,如果是,您将如何整理它们? 【参考方案1】:这是一个简单而干净的解决方案。如果您有任何问题或需要其他任何东西,请告诉我。
SELECT A.[DATE],
A.[TIME],
A.[User],
A.[Entry]
FROM @Table A
CROSS APPLY(SELECT MIN([Date]) FROM @Table WHERE [Entry] LIKE 'Some Job%') CA_min(start_dt)
CROSS APPLY(SELECT MAX([Date]) FROM @Table WHERE [Entry] LIKE 'Some Job%') CA_max(end_dt)
WHERE [DATE] BETWEEN start_dt AND end_dt
【讨论】:
CROSS APPLY 基本上就像一个子查询,但使用交叉应用允许我在 where 子句中引用它。你熟悉子查询吗?【参考方案2】:试试ORDER-BY
和ASC / DESC
WITH Data (Date, Time, User, Entry) AS
(
SELECT Date, Time, User, Entry
FROM data
ORDER BY DATE ASC, TIME ASC
)
SELECT TOP ((SELECT COUNT(*) FROM Data) - 2) *
FROM (
SELECT TOP ((SELECT COUNT(*) FROM Data) - 1) *
FROM Data
ORDER BY Date ASC, Time ASC -- all rows without the end-row
) tmp
ORDER BY Date ASC, Time DESC -- all rows without the start-row
或者更简单的WHERE
-Clause。
SELECT Date, Time, User, Entry
FROM data
WHERE Entry NOT LIKE '%JOB STARTED%'
AND Entry NOT LIKE '%JOB FINISHED%'
【讨论】:
【参考方案3】:测试数据
DECLARE @Table TABLE ([DATE] Datetime ,[TIME] TIME, [USER] VARCHAR(100) , [ENTRY] VARCHAR(1000))
INSERT INTO @Table VALUES
('2015-04-13 07:30:15.150','07:30:15','CmdLne','SOME JOB STARTED FOR PROCESSING DATE 13/04/2015'),
('2015-04-13 07:31:15.150','07:31:15','CmdLne','PROCESSED 10 WHATEVERS'),
('2015-04-13 07:32:25.150','07:32:25','CmdLne','PROCESSED 10 SOMETHINGS'),
('2015-04-13 07:33:33.150','07:33:33','CmdLne','PROCESSED 40 XYZ'),
('2015-04-13 07:33:34.150','07:33:34','CmdLne','SOME JOB FINISHED FOR PROCESSING DATE 13/04/2015') ,
('2015-04-13 07:30:15.150','07:30:15','Powershell','SOME JOB STARTED FOR PROCESSING DATE 13/04/2015'),
('2015-04-13 07:31:15.150','07:31:15','Powershell','PROCESSED 10 WHATEVERS'),
('2015-04-13 07:32:25.150','07:32:25','Powershell','PROCESSED 10 SOMETHINGS'),
('2015-04-13 07:33:33.150','07:33:33','Powershell','PROCESSED 40 XYZ'),
('2015-04-13 07:33:34.150','07:33:34','Powershell','SOME JOB FINISHED FOR PROCESSING DATE 13/04/2015')
查询
SELECT t1.*
FROM @Table t1
WHERE t1.[DATE] >= ( SELECT TOP 1 [DATE] FROM @Table
WHERE [ENTRY] LIKE '%SOME JOB STARTED%'
AND t1.[USER] = [USER])
AND t1.[DATE] <= ( SELECT TOP 1 [DATE] FROM @Table
WHERE [ENTRY] LIKE '%SOME JOB FINISHED%'
AND t1.[USER] = [USER])
AND t1.[USER] = 'CmdLne' --<--
【讨论】:
【参考方案4】:数据样本
DECLARE @Table TABLE
(
[DATE] DATETIME ,
[TIME] TIME ,
[USER] VARCHAR(100) ,
[ENTRY] VARCHAR(1000)
)
INSERT INTO @Table
VALUES ( '2015-04-13 07:30:15.150', '07:30:15', 'CmdLne',
'SOME JOB STARTED FOR PROCESSING DATE 13/04/2015' ),
( '2015-04-13 07:31:15.150', '07:31:15', 'CmdLne',
'PROCESSED 10 WHATEVERS' ),
( '2015-04-13 07:32:25.150', '07:32:25', 'CmdLne',
'PROCESSED 10 SOMETHINGS' ),
( '2015-04-13 07:33:33.150', '07:33:33', 'CmdLne', 'PROCESSED 40 XYZ' ),
( '2015-04-13 07:33:34.150', '07:33:34', 'CmdLne',
'SOME JOB FINISHED FOR PROCESSING DATE 13/04/2015' ) ,
( '2015-04-13 07:30:15.150', '07:30:15', 'Powershell',
'SOME JOB STARTED FOR PROCESSING DATE 13/04/2015' ),
( '2015-04-13 07:31:15.150', '07:31:15', 'Powershell',
'PROCESSED 10 WHATEVERS' ),
( '2015-04-13 07:32:25.150', '07:32:25', 'Powershell',
'PROCESSED 10 SOMETHINGS' ),
( '2015-04-13 07:33:33.150', '07:33:33', 'Powershell',
'PROCESSED 40 XYZ' ),
( '2015-04-13 07:33:34.150', '07:33:34', 'Powershell',
'SOME JOB FINISHED FOR PROCESSING DATE 13/04/2015' )
最终查询
SELECT *
FROM ( SELECT ROW_NUMBER() OVER ( PARTITION BY CONVERT(DATE, T.DATE),
T.[USER] ORDER BY T.DATE ) AS RN ,
*
FROM @Table AS T
) T
WHERE T.RN NOT IN ( 1, 2 )
【讨论】:
以上是关于SQL - 选择两个字符串行之间的所有行的主要内容,如果未能解决你的问题,请参考以下文章