当前位置: 首页 > 面试题库 >

T-SQL联接可获取配对和非配对的开始和停止记录

陶鹏
2023-03-14
问题内容

我有一个设计不良的表,我没有设计该表,无法修复/更改
该表,因为有写入该表的第三方黑莓应用程序。最重要的是,有
一个开始记录和一个停止记录,用于跟踪没有连接的事件或
验证是否存在匹配项的事件。黑莓应用程序不执行任何操作将这些
记录绑定在一起。我试着在其自身上创建一个连接,并
以开始和结束以完全外部联接来创建临时表。该
问题是,我有重复条目被该条目将被标记为
没有伴侣。现有数据的行在开始和结束
记录上都没有配对。我已经搜索了答案,发现了一些很接近的答案,
已经带我走了这么远。我知道这是一篇很长的帖子,对此感到抱歉。

有一个单一的令人惊讶地具有主键表。没有
枢轴/相交表。结构是

ID (int PK)
activityType varchar
beginEnd varchar ('begin' or 'end')
businessKey varchar nullable
date DATETIME
technician varchar

表中也包含以下几列,但它们可以为空,并且对查询不重要。

dateSubmitted DATETIME
gpsLatitude float
gpsLongitude float
note varchar
odometer int

The query that I have now that still leaves dupes: Showing and sorting ID and
EndID are for debugging only

DECLARE @DateFrom DATETIME
DECLARE @DateTo DATETIME
SET @DateFrom='20101101'
SET @DateTo='20101102'
DECLARE @Incomplete VARCHAR(15)
SET @Incomplete = 'Incomplete'

DECLARE @StartEvents TABLE
(
[id] [numeric](19, 0) NOT NULL,
[activityType] [varchar](255) NOT NULL,
[beginEnd] [varchar](255) NULL,
[businessKey] [varchar](255) NULL,
[date] [datetime] NOT NULL,
[dateSubmitted] [datetime] NULL,
[gpsLatitude] [float] NULL,
[gpsLongitude] [float] NULL,
[note] [varchar](255) NULL,
[odometer] [int] NULL,
[technician] [varchar](255) NOT NULL
)

INSERT     @StartEvents
       ([ID],[activityType],[beginEnd],[businessKey],[date],[dateSubmitted],[gpsLatitude]
            ,[gpsLongitude],[note],[odometer],[technician])
SELECT      *
FROM        dbo.TimeEntry
WHERE 
[date] between @DateFrom AND @DateTo
AND beginEnd = 'Begin'
--AND [technician] = 'FRED'
ORDER by technician
------------------------------------------------------------
DECLARE @EndEvents TABLE
(
[id] [numeric](19, 0) NOT NULL,
[activityType] [varchar](255) NOT NULL,
[beginEnd] [varchar](255) NULL,
[businessKey] [varchar](255) NULL,
[date] [datetime] NOT NULL,
[dateSubmitted] [datetime] NULL,
[gpsLatitude] [float] NULL,
[gpsLongitude] [float] NULL,
[note] [varchar](255) NULL,
[odometer] [int] NULL,
[technician] [varchar](255) NOT NULL
)

INSERT     @EndEvents
       ([ID],[activityType],[beginEnd],[businessKey],[date],[dateSubmitted],[gpsLatitude]
            ,[gpsLongitude],[note],[odometer],[technician])
SELECT      *
FROM        dbo.TimeEntry
WHERE 
[date] between @DateFrom AND @DateTo AND
beginEnd = 'End'
--AND [technician] = 'FRED'
ORDER by technician

-- And then a conventional SELECT
SELECT     
StartEvents.id 
,EndEvents.id AS EndID
,COALESCE(
    StartEvents.activityType ,EndEvents.activityType ,'Not Available'
    ) AS ActivityType
--,StartEvents.beginEnd as [Begin] 
--,EndEvents.beginEnd AS [End]
,COALESCE (
    convert(VARCHAR(12), StartEvents.[date], 103), 
    convert(VARCHAR(12), EndEvents.[date], 103), @Incomplete
    ) as [Event Date] 
,COALESCE (
    convert(VARCHAR(12), EndEvents.[date], 103), @Incomplete 
    ) as [End Date] 
,COALESCE(
    CONVERT(VARCHAR(5) , StartEvents.dateSubmitted , 108) , @Incomplete
        ) AS StartTime
,COALESCE(
    CONVERT(VARCHAR(5) , EndEvents.dateSubmitted , 108) , @Incomplete
        ) AS EndTime
,COALESCE(
    StartEvents.note, EndEvents.note, ''
    ) as [Note]
,COALESCE(
    StartEvents.technician,EndEvents.technician,'Not Available'
    ) AS Technician

FROM         
@StartEvents As StartEvents

FULL OUTER JOIN

@EndEvents AS EndEvents ON 
StartEvents.technician = EndEvents.technician AND 
StartEvents.businessKey = EndEvents.businessKey AND 
StartEvents.activityType = EndEvents.activityType 
AND convert(VARCHAR(12), StartEvents.[date], 103) = convert(VARCHAR(12), EndEvents.[date], 103)

-- WHERE 
    --StartEvents.[date] between @DateFrom AND @DateTo OR 
    --StartEvents.[dateSubmitted] between @DateFrom AND @DateTo 
ORDER BY 
    StartEvents.Technician,
    ID,ENDID

DATA:

id,activityType,beginEnd,businessKey,date,dateSubmitted,gpsLatitude,gpsLongitude,note,odometer,technician
23569,Standby,Begin,,2010-11-01 08:00:13.000,2010-11-01 08:26:45.533,34.139,-77.895,#1140,28766,barthur@fubar.com
23570,Travel,Begin,00100228002,2010-11-01 07:00:44.000,2010-11-01 08:34:15.370,35.0634,-80.7668,,18706,creneau@fubar.com
23571,Standby,End,,2010-11-01 08:30:08.000,2010-11-01 08:35:20.463,34.0918,-77.9002,#1140,28766,barthur@fubar.com
23572,Travel,Begin,00100226488,2010-11-01 08:30:41.000,2010-11-01 08:36:56.420,34.0918,-77.9002,,28766,barthur@fubar.com
23573,Travel,End,00100226488,2010-11-01 08:45:00.000,2010-11-01 08:44:15.553,34.0918,-77.9002,,28768,barthur@fubar.com
23574,OnSite,Begin,00100226488,2010-11-01 08:45:41.000,2010-11-01 09:24:23.943,34.0918,-77.9002,,0,barthur@fubar.com
23575,OnSite,End,00100226488,2010-11-01 09:30:10.000,2010-11-01 09:33:19.953,34.0918,-77.9002,,28768,barthur@fubar.com
23576,Travel,Begin,00100228137,2010-11-01 09:30:20.000,2010-11-01 09:34:57.330,34.0918,-77.9002,,28768,barthur@fubar.com
23577,Travel,End,00100228137,2010-11-01 09:45:51.000,2010-11-01 09:42:39.230,34.0918,-77.9002,,28771,barthur@fubar.com
23578,Travel,Begin,00100228138,2010-11-01 09:00:23.000,2010-11-01 09:58:22.857,34.9827,-80.5365,,18749,creneau@fubar.com
23579,OnSite,Begin,00100228137,2010-11-01 09:45:47.000,2010-11-01 10:41:10.563,34.139,-77.895,,0,barthur@fubar.com
23580,OnSite,End,00100228137,2010-11-01 10:45:43.000,2010-11-01 11:09:14.393,34.139,-77.895,,28771,barthur@fubar.com
23581,OnSite,Begin,00100228142,2010-11-01 10:45:42.000,2010-11-01 11:29:26.447,34.139,-77.895,#1015,28771,barthur@fubar.com
23582,OnSite,End,00100228142,2010-11-01 11:15:18.000,2010-11-01 11:55:28.603,34.139,-77.895,#1015,28771,barthur@fubar.com
23583,Travel,Begin,,2010-11-01 11:15:06.000,2010-11-01 11:56:01.633,34.139,-77.895,"#1142 Fuel, #1154 Tickets",28771,barthur@fubar.com
23584,Travel,End,,2010-11-01 12:00:47.000,2010-11-01 12:07:54.867,34.139,-77.895,"#1154, #1142",28774,barthur@fubar.com
23585,Travel,End,,2010-11-01 12:00:47.000,2010-11-01 12:07:55.087,34.139,-77.895,"#1154, #1142",28774,barthur@fubar.com
23586,Break,Begin,,2010-11-01 12:00:26.000,2010-11-01 12:08:06.007,34.139,-77.895,#1153,28774,barthur@fubar.com
23587,Travel,End,,2010-11-01 12:00:47.000,2010-11-01 12:08:06.040,34.139,-77.895,"#1154, #1142",28774,barthur@fubar.com
23588,Break,Begin,,2010-11-01 12:00:26.000,2010-11-01 12:08:06.070,34.139,-77.895,#1153,28774,barthur@fubar.com
23589,Travel,End,,2010-11-01 12:00:47.000,2010-11-01 12:16:02.673,34.139,-77.895,"#1154, #1142",28774,barthur@fubar.com
23590,Travel,End,,2010-11-01 12:00:47.000,2010-11-01 12:16:14.220,34.139,-77.895,"#1154, #1142",28774,barthur@fubar.com
23591,Travel,Begin,00100228000,2010-11-01 11:45:19.000,2010-11-01 12:35:46.363,35.0634,-80.7668,,18760,creneau@fubar.com
23592,Travel,Begin,00100227980,2010-11-01 13:15:14.000,2010-11-01 13:58:51.050,34.0918,-77.9002,,28774,barthur@fubar.com
23593,Travel,Begin,00100227980,2010-11-01 13:15:14.000,2010-11-01 13:59:03.830,34.0918,-77.9002,,28774,barthur@fubar.com
23594,Travel,Begin,00100227980,2010-11-01 13:15:14.000,2010-11-01 13:59:03.893,34.1594,-77.8929,,28774,barthur@fubar.com
23595,Travel,Begin,00100227980,2010-11-01 13:15:14.000,2010-11-01 13:59:03.940,34.1594,-77.8929,,28774,barthur@fubar.com
23596,Travel,Begin,00100227980,2010-11-01 13:15:14.000,2010-11-01 13:59:15.880,34.1594,-77.8929,,28774,barthur@fubar.com
23597,Travel,Begin,00100227980,2010-11-01 13:15:14.000,2010-11-01 13:59:15.927,34.2743,-77.8668,,28774,barthur@fubar.com
23598,Travel,Begin,00100227980,2010-11-01 13:15:14.000,2010-11-01 13:59:15.987,34.2743,-77.8668,,28774,barthur@fubar.com
23599,Travel,Begin,00100228166,2010-11-01 14:00:13.000,2010-11-01 14:29:45.320,35.0634,-80.7668,,18779,creneau@fubar.com
23600,Travel,End,00100227980,2010-11-01 15:15:58.000,2010-11-01 15:15:40.403,35.3414,-78.0325,,28880,barthur@fubar.com
23601,Travel,Begin,00100228205,2010-11-01 15:30:46.000,2010-11-01 15:41:41.810,35.0661,-80.8376,,18781,creneau@fubar.com
23602,OnSite,Begin,00100227980,2010-11-01 15:15:23.000,2010-11-01 15:59:45.203,35.3873,-77.9395,,28880,barthur@fubar.com
23603,OnSite,End,00100227980,2010-11-01 16:15:22.000,2010-11-01 16:06:09.150,35.3873,-77.9395,,28880,barthur@fubar.com
23604,Travel,Begin,00100228007,2010-11-01 16:15:15.000,2010-11-01 16:15:25.253,35.3873,-77.9395,,28880,barthur@fubar.com
23605,Travel,Begin,,2010-11-01 16:15:12.000,2010-11-01 16:20:49.933,35.0445,-80.8227,Return trip home,18785,creneau@fubar.com
23606,Travel,End,00100228007,2010-11-01 16:30:48.000,2010-11-01 16:26:43.360,35.3873,-77.9395,,28884,barthur@fubar.com
23607,Travel,End,,2010-11-01 17:30:14.000,2010-11-01 17:23:57.897,35.2724,-81.1577,Return trip home,18822,creneau@fubar.com
23608,OnSite,Begin,00100228007,2010-11-01 16:30:48.000,2010-11-01 18:38:32.700,35.3941,-77.994,,28880,barthur@fubar.com
23609,Travel,Begin,00100228209,2010-11-01 17:45:16.000,2010-11-01 18:39:05.683,35.3941,-77.994,,28884,barthur@fubar.com
23610,OnSite,End,00100228007,2010-11-01 17:45:52.000,2010-11-01 18:41:36.980,35.3941,-77.994,,28884,barthur@fubar.com
23611,OnSite,Begin,00100228209,2010-11-01 18:00:38.000,2010-11-01 18:42:12.763,35.3941,-77.994,,28888,barthur@fubar.com
23612,OnSite,End,00100228209,2010-11-01 18:30:44.000,2010-11-01 18:43:29.123,35.3941,-77.994,,28888,barthur@fubar.com
23613,Standby,Begin,,2010-11-01 18:30:58.000,2010-11-01 18:45:28.857,35.3941,-77.994,#1157 ergo,28888,barthur@fubar.com
23614,Standby,End,,2010-11-01 18:45:26.000,2010-11-01 18:46:01.167,35.3941,-77.994,#1157 ergo redo,28888,barthur@fubar.com
23615,Travel,Begin,,2010-11-01 18:45:24.000,2010-11-01 18:47:37.803,35.3941,-77.994,RTN,28888,barthur@fubar.com
23616,Travel,End,,2010-11-01 20:45:05.000,2010-11-01 20:34:39.433,34.139,-77.895,#1142 Fueled,28990,barthur@fubar.com

在此图像中,您看到突出显示的行显示了6个结束时间,
并且开始时间相同。记录14和15显示2开始且没有结束。


问题答案:

这是滥用row_number函数的方法。请检查注释以获取一些解释。

;with Seq as (
    -- Create a master sequence of events
    -- Trust the date column to be accurate (don't match a Begin to an earlier End)
    select id, activitytype, beginend
        , coalesce(businesskey, '') as businesskey -- Needed to match nulls as equal
        , [date], technician, note
        , row_number() over (partition by technician, businesskey, activitytype order by [date], beginend, id) as rownumber
    from TimeEntry
)
select b.id as BeginID
    , e.id as EndID
    , coalesce(b.technician, e.technician) as Technician
    , coalesce(b.businesskey, e.businesskey) as BusinessKey
    , coalesce(b.activitytype, e.activitytype) as ActivityType
    , coalesce(convert(char(10), b.[date], 103), 'Incomplete') as BeginDate
    , coalesce(convert(char(10), e.[date], 103), 'Incomplete') as EndDate
    , coalesce(convert(char(5), b.[date], 108), 'Incomplete') as BeginTime
    , coalesce(convert(char(5), e.[date], 108), 'Incomplete') as EndTime
    , b.note as BeginNote
    , e.note as EndNote
from (select * from Seq where beginend = 'Begin') b -- Get all Begins
    full outer join (select * from Seq where beginend = 'End') e -- Get all Ends
        on b.technician = e.technician
            and b.businesskey = e.businesskey
            and b.activitytype = e.activitytype
            and b.rownumber = e.rownumber - 1 -- Match a Begin with only the very next End of that type
order by coalesce(b.[date], e.[date])
    , coalesce(b.id, e.id)
    , coalesce(b.technician, e.technician)
    , coalesce(b.businesskey, e.businesskey)
    , coalesce(b.activitytype, e.activitytype)

And the SQL Fiddle should anyone want the
DDL or demo.



 类似资料:
  • 我正在做一个游戏,里面有背景音乐。我想添加一个启动和停止音乐的静音按钮,但我不知道怎么做。创建音乐的方法是: 我想做的是在按钮的动作处理程序中,我想添加一个静音按钮,如果用户愿意,它可以启动和停止音频。所以它应该是这样的:如果(e.getSource()==muteButton){//启动和停止音乐} 我该怎么做?谢谢你的帮助!

  • 所以这是我需要解决的大事。我有Visual C#应用程序。在这个应用程序中,用户输入数据并单击Execute。当他们点击执行时,核心方法开始在新线程中,在那个线程和方法是一个循环。不断地使用方法调用器,我向UserForm发送更新,循环实际上在做什么。例如,像这样,我在每个cicle中更新progressBar。

  • 问题内容: 我有两个表: 我希望将事件数据添加到视频数据中,以便为每个事件获取视频文件名。记录器字段用于指定在事件发生时可操作的记录器,并协助多个记录器同时记录视频。 如果我不关心没有视频的事件,那很好(我可以获取SQL),但是在我的情况下,我希望显示最接近的视频文件名和秒数差异。 编辑 样本数据 大事记 视频 结果(EventID,VideoID,文件名,IsBetween,secondsDif

  • 问题内容: 我有当前日期,还有一个常数,它指示星期几。我想基于该常数获取一周的开始日期。如果我将一周的第一天硬编码为星期一(或其他任何东西),那么这很简单。但是一周的第一天一直在变化。因此,我不想在每次更改第一天时都更改代码。 这是我尝试使用Java的Calendar的方法: 我想获取一周的开始日期。上面的函数返回星期的第一天,并且星期开始日期被硬编码为星期六。每当星期开始日期以上的要求发生变化时

  • 问题内容: 我有下表 帐户 这是DDL 这是我的查询 查询的主要目的是选择具有层次关系的数据,分别是PARENT_ACCOUNT_ID和ACCOUNT_ID,但是我得到了查询返回的重复数据 任何建议,不胜感激。谢谢 问题答案: 为什么不简单地: ?

  • 问题内容: 我有以下五个表: 互联网服务提供商 产品 联系 添加在 插件/产品(多对多关系的数据透视表)。 每个产品都链接到一个ISP,每个连接都列在一个产品上。通过使用数据透视表,每个产品可以具有许多附加组件(该数据透视表仅具有2个字段,一个字段用于产品ID,一个字段用于AddOn ID)。 我感兴趣的结果是列出的插件的每个连接(为此,我使用MySQL的GROUP_CONCAT,以逗号分隔列表的