AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 106948
Accepted
ΩmegaMan
ΩmegaMan
Asked: 2015-07-15 11:31:16 +0800 CST2015-07-15 11:31:16 +0800 CST 2015-07-15 11:31:16 +0800 CST

确定差距记录,填写并返回结果

  • 772

以下工作代码针对 SQL-Server 2012,我已将实际问题提炼为可管理的场景,下面显示的代码示例也在SQL Fiddle.

我寻求有关使用 CTE 和临时表的最佳实践的反馈,并且想知道是否可以简化以下内容。

(请注意,这也在代码审查(插入差距记录报告流程)中被问到,到目前为止没有任何回应。)

前提

存在两个表,其中包含代理和管理的时间戳事件。将在代理表上运行报告。但在代理表中,如果事件间隔超过 5 小时,则必须从事件管理表中为该间隔填写生成的报告。

代理人

CREATE TABLE AgentInteractions
(
   [Event]      VARCHAR(12) NOT NULL, 
   [Timestamp] [DateTime] NOT NULL
);


INSERT INTO dbo.AgentInteractions( Event, TimeStamp  )
VALUES ( 'Alpha', '24-Jan-2018 3:04:00 PM' ),
       ( 'Beta', '24-Jan-2018 10:04:00 PM' ),  -- Gap 7 hours
       ( 'Omega', '25-Jan-2018 2:04:00 AM' );  -- No Gap

管理

CREATE TABLE ManagementInteractions
(
  [Event]      VARCHAR(12) NOT NULL, 
  [Timestamp] [DateTime] NOT NULL
);


INSERT INTO dbo.ManagementInteractions( Event, TimeStamp  )
VALUES ( '5pm',      '24-Jan-2018 5:00:00 PM' ),  -- Gap Filler #1
       ( '8pm',      '24-Jan-2018 8:00:00 PM' ),  -- Gap Filler #2
       ( 'Midnight', '25-Jan-2018 12:00:00 AM' ); -- Not used

初步报告(或第一步)

使用以下将报告放入临时表的 sql,它计算行之间的时间差并设置原始数据中不存在的序列。

CTE 到临时表

IF OBJECT_ID('tempdb..#Actions') IS NOT NULL DROP TABLE #Actions;

WITH AgentActions AS 
( SELECT  ROW_NUMBER() OVER ( ORDER BY [Timestamp] ) AS [Sequence], -- Create an index number ordered by time.
          Event ,
          Timestamp
  FROM  AgentInteractions
)
SELECT  CAST('Agent' AS VARCHAR(20)) AS [Origin] ,
            AgentActions.Sequence ,
            AgentActions.Event ,
            ( SELECT    Other.Timestamp
              FROM      AgentActions Other
              WHERE     Other.Sequence = AgentActions.Sequence - 1
            ) AS Previous ,
            AgentActions.Timestamp ,
            ISNULL(DATEDIFF(HOUR,
                            ( SELECT    Other.Timestamp
                              FROM      AgentActions Other
                              WHERE     Other.Sequence = AgentActions.Sequence - 1), 
                            AgentActions.Timestamp), 
                            0) AS TimeFromLastPoint
    INTO    #Actions
    FROM    AgentActions;

select into 的结果#Actions,注意 7 小时的差距:

在此处输入图像描述

确定差距

以下 sql 确定差距,并插入管理表中的记录以填补差距。

将管理事件插入差距

WITH Gaps AS 
( SELECT   AC.Origin ,
           AC.Sequence ,
           AC.Event ,
           AC.Previous ,
           AC.Timestamp ,
           AC.TimeFromLastPoint
  FROM     #Actions AC
  WHERE    AC.TimeFromLastPoint > 5
)
INSERT  INTO #Actions ( [Origin] , [Event] , [Timestamp] , TimeFromLastPoint)
            SELECT  'Management' ,
                    [Event] ,
                    [Timestamp] ,
                    0                      -- We will figure this out after the insert.
            FROM    ManagementInteractions MAN
            WHERE   EXISTS ( SELECT *
                             FROM   Gaps
                             WHERE  MAN.Timestamp BETWEEN Gaps.Previous
                                                  AND     Gaps.Timestamp );

SELECT Origin , Sequence , Event , Previous , Timestamp , TimeFromLastPoint 
FROM #Actions ORDER BY Timestamp;

选择的结果。

在此处输入图像描述

总结报告

最终报告执行步骤 1 中的操作,重新排序并确定所有点之间的持续时间。

CTE Deja-vu 最终报告

WITH Combined AS 
( 
   SELECT Origin,
          ROW_NUMBER() OVER ( ORDER BY [Timestamp] ) AS [Sequence], -- Create an index number ordered by time.
          Event ,
          Timestamp
    FROM  #Actions
)
SELECT  Combined.Origin,
        Combined.Sequence ,
        Combined.Event ,
        ( SELECT    Other.Timestamp
          FROM      Combined Other
          WHERE     Other.Sequence = Combined.Sequence - 1
        ) AS Previous ,
        Combined.Timestamp ,
        ISNULL(DATEDIFF(HOUR,
                        ( SELECT    Other.Timestamp
                          FROM      Combined Other
                          WHERE     Other.Sequence = Combined.Sequence
                                    - 1
                        ), Combined.Timestamp), 0) AS TimeFromLastPoint

FROM  Combined;

这是结果

在此处输入图像描述

概括

是否可以组合任何步骤,或者我应该使用或避免使用上述 sql 代码的任何做法?

sql-server sql-server-2012
  • 1 1 个回答
  • 701 Views

1 个回答

  • Voted
  1. Best Answer
    Geoff Patterson
    2015-07-15T12:47:25+08:002015-07-15T12:47:25+08:00

    我认为您提出的方法非常好。dbo.AgentInteractions这是一个建议的简化,通过使用新的 SQL Server 2012 LAG 函数和 CTE 将逻辑提炼成单个查询(也在SQL Fiddle表单中)来避免自连接。

    WITH AgentActions AS (
        -- Sequence the agent actions
        SELECT a.Event,
            LAG(a.TimeStamp, 1) OVER (ORDER BY TimeStamp ASC) AS Previous,
            a.TimeStamp,
            DATEDIFF(HOUR, LAG(a.TimeStamp, 1) OVER (ORDER BY TimeStamp ASC), a.TimeStamp) AS TimeFromLastPoint
        FROM dbo.AgentInteractions a
    ),
    allActionsToReport AS (
        --  Agent action
        SELECT 'Agent' AS Origin, a.Event, a.TimeStamp
        FROM AgentActions a
        UNION ALL
        -- Any management actions during a gap of > 5 hours between agent interactions
        SELECT 'Management' AS Origin, m.event, m.TimeStamp
        FROM AgentActions a
        JOIN ManagementInteractions m
            ON m.TimeStamp BETWEEN a.Previous AND a.TimeStamp
        WHERE a.TimeFromLastPoint > 5
    )
    -- For all actions (with gaps already filled), perform final sequencing
    SELECT a.Origin,
        ROW_NUMBER() OVER (ORDER BY a.TimeStamp ASC) AS Sequence,
        a.Event,
        LAG(a.TimeStamp, 1) OVER (ORDER BY TimeStamp ASC) AS Previous,
        a.TimeStamp,
        ISNULL(DATEDIFF(HOUR, LAG(a.TimeStamp, 1) OVER (ORDER BY TimeStamp ASC), a.TimeStamp), 0) AS TimeFromLastPoint
    FROM allActionsToReport a
    

    通过查看此单一查询版本的查询计划,它完全符合您的预期:按时间戳对代理操作进行排序,通过访问管理操作来填补空白,然后对这组组合结果操作进行排序为了做最后的排序:

    在此处输入图像描述

    • 2

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve