SQL - 在日志记录场景中每组组合 3 行
SQL - Combining 3 rows per group in a logging scenario
出于成本和性能原因,我已经重新设计了 API 的日志系统,以使用 Azure Table 存储,而不是使用 SQL 存储。我现在正在将我们的遗留日志迁移到新系统。我正在为每个 table 构建一个 SQL 查询,它将旧字段映射到新字段,目的是导出到 CSV,然后导入到 Azure。
到目前为止,还不错。然而,以前系统的一个工件是它对每个请求记录 3 次——调用开始、调用响应和调用结束——而新的系统只将调用记录为一个日志(同样,出于成本和性能原因)。
- 一些共同的字段对于所有三个相关日志都是共同的,例如唯一标识调用的会话。
- 有些字段我只想要第一个日志的值,例如日期在第二个和第三个日志中可能会相差几秒。
- 一些字段是出于三个不同的目的而共享的,例如参数给出呼叫开始的输入模型、呼叫响应的输出模型和呼叫结束的 HTTP 响应(例如 OK)。
- 有些字段未用于两个目的,例如ExecutionTime 对于呼叫开始和呼叫响应是 -1,对于呼叫结束是一个以毫秒为单位的值。
如何"roll up"将每组 3 行的组合并为一行? 我试过使用 DISTINCT
和 GROUP BY
,但一些信息相互冲突的事实使它变得非常困难。抱歉,我的 SQL 不够好,无法真正解释我的要求 - 所以也许举个例子会更清楚:
我的示例:
SQL:
SELECT * FROM [dbo].[Log]
结果:
+---------+---------------------+-------+------------+---------------+---------------+-----------------+--+
| Session | Date | Level | Context | Message | ExecutionTime | Parameters | |
+---------+---------------------+-------+------------+---------------+---------------+-----------------+--+
| 84248B7 | 2014-07-20 19:16:15 | INFO | GET v1/abc | Call Begin | -1 | {"Input":"xx"} | |
| 84248B7 | 2014-07-20 19:16:15 | INFO | GET v1/abc | Call Response | -1 | {"Output":"yy"} | |
| 84248B7 | 2014-07-20 19:16:15 | INFO | GET v1/abc | Call End | 123 | OK | |
| F76BCBB | 2014-07-20 19:16:17 | ERROR | GET v1/def | Call Begin | -1 | {"Input":"ww"} | |
| F76BCBB | 2014-07-20 19:16:18 | ERROR | GET v1/def | Call Response | -1 | {"Output":"vv"} | |
| F76BCBB | 2014-07-20 19:16:18 | ERROR | GET v1/def | Call End | 456 | BadRequest | |
+---------+---------------------+-------+------------+---------------+---------------+-----------------+--+
我想要的例子:
SQL:
[Need to write this query]
结果:
+---------------------+-------+------------+----------+---------------+----------------+-----------------+--------------+
| Date | Level | Context | Message | ExecutionTime | InputModel | OutputModel | HttpResponse |
+---------------------+-------+------------+----------+---------------+----------------+-----------------+--------------+
| 2014-07-20 19:16:15 | INFO | GET v1/abc | Api Call | 123 | {"Input":"xx"} | {"Output":"yy"} | OK |
| 2014-07-20 19:16:17 | ERROR | GET v1/def | Api Call | 456 | {"Input":"ww"} | {"Output":"vv"} | BadRequest |
+---------------------+-------+------------+----------+---------------+----------------+-----------------+--------------+
select L1.Session, L1.Date, L1.Level, L1.Context, 'Api Call' AS Message,
L3.ExecutionTime,
L1.Parameters as InputModel,
L2.Parameters as OutputModel,
L3.Parameters as HttpResponse
from Log L1
inner join Log L2 ON L1.Session = L2.Session
inner join Log L3 ON L1.Session = L3.Session
where L1.Message = 'Call Begin'
and L2.Message = 'Call Response'
and L3.Message = 'Call End'
这适用于您的示例。
出于成本和性能原因,我已经重新设计了 API 的日志系统,以使用 Azure Table 存储,而不是使用 SQL 存储。我现在正在将我们的遗留日志迁移到新系统。我正在为每个 table 构建一个 SQL 查询,它将旧字段映射到新字段,目的是导出到 CSV,然后导入到 Azure。
到目前为止,还不错。然而,以前系统的一个工件是它对每个请求记录 3 次——调用开始、调用响应和调用结束——而新的系统只将调用记录为一个日志(同样,出于成本和性能原因)。
- 一些共同的字段对于所有三个相关日志都是共同的,例如唯一标识调用的会话。
- 有些字段我只想要第一个日志的值,例如日期在第二个和第三个日志中可能会相差几秒。
- 一些字段是出于三个不同的目的而共享的,例如参数给出呼叫开始的输入模型、呼叫响应的输出模型和呼叫结束的 HTTP 响应(例如 OK)。
- 有些字段未用于两个目的,例如ExecutionTime 对于呼叫开始和呼叫响应是 -1,对于呼叫结束是一个以毫秒为单位的值。
如何"roll up"将每组 3 行的组合并为一行? 我试过使用 DISTINCT
和 GROUP BY
,但一些信息相互冲突的事实使它变得非常困难。抱歉,我的 SQL 不够好,无法真正解释我的要求 - 所以也许举个例子会更清楚:
我的示例:
SQL:
SELECT * FROM [dbo].[Log]
结果:
+---------+---------------------+-------+------------+---------------+---------------+-----------------+--+
| Session | Date | Level | Context | Message | ExecutionTime | Parameters | |
+---------+---------------------+-------+------------+---------------+---------------+-----------------+--+
| 84248B7 | 2014-07-20 19:16:15 | INFO | GET v1/abc | Call Begin | -1 | {"Input":"xx"} | |
| 84248B7 | 2014-07-20 19:16:15 | INFO | GET v1/abc | Call Response | -1 | {"Output":"yy"} | |
| 84248B7 | 2014-07-20 19:16:15 | INFO | GET v1/abc | Call End | 123 | OK | |
| F76BCBB | 2014-07-20 19:16:17 | ERROR | GET v1/def | Call Begin | -1 | {"Input":"ww"} | |
| F76BCBB | 2014-07-20 19:16:18 | ERROR | GET v1/def | Call Response | -1 | {"Output":"vv"} | |
| F76BCBB | 2014-07-20 19:16:18 | ERROR | GET v1/def | Call End | 456 | BadRequest | |
+---------+---------------------+-------+------------+---------------+---------------+-----------------+--+
我想要的例子:
SQL:
[Need to write this query]
结果:
+---------------------+-------+------------+----------+---------------+----------------+-----------------+--------------+
| Date | Level | Context | Message | ExecutionTime | InputModel | OutputModel | HttpResponse |
+---------------------+-------+------------+----------+---------------+----------------+-----------------+--------------+
| 2014-07-20 19:16:15 | INFO | GET v1/abc | Api Call | 123 | {"Input":"xx"} | {"Output":"yy"} | OK |
| 2014-07-20 19:16:17 | ERROR | GET v1/def | Api Call | 456 | {"Input":"ww"} | {"Output":"vv"} | BadRequest |
+---------------------+-------+------------+----------+---------------+----------------+-----------------+--------------+
select L1.Session, L1.Date, L1.Level, L1.Context, 'Api Call' AS Message,
L3.ExecutionTime,
L1.Parameters as InputModel,
L2.Parameters as OutputModel,
L3.Parameters as HttpResponse
from Log L1
inner join Log L2 ON L1.Session = L2.Session
inner join Log L3 ON L1.Session = L3.Session
where L1.Message = 'Call Begin'
and L2.Message = 'Call Response'
and L3.Message = 'Call End'
这适用于您的示例。