我有一个表记录案例的请求和响应,以及每次发生的时间。我的问题是,特定响应与其响应的请求之间没有直接关联。为了使事情变得更加困难,对一个请求可能会有多个响应,并且请求和响应不会始终整理 - 您可能有两个请求后跟两个响应,这意味着第一个响应与第一个请求相关,第二个响应与第二个请求有关。下面简化的表格给出了每种情况的例子:
Case_Id Subject Date
123 Request 2014-12-03 15:48:02
123 Response 2014-12-03 16:01:45
123 Response 2014-12-03 17:32:23
123 Request 2015-04-10 12:12:17
123 Request 2015-04-10 12:13:34
123 Response 2015-04-10 13:31:20
123 Response 2014-04-10 13:37:12
234 Request 2014-12-03 12:12:20
234 Response 2014-12-03 12:20:23
234 Request 2015-03-03 15:09:44
234 Response 2015-03-03 16:23:54
我想要做的是找到与案例中每个请求相对应的第一个响应,以便我可以计算响应所花费的时间。所以这个查询的输出应该是:
Case_Id Request Time Response Time
123 2014-12-03 15:48:02 2014-12-03 16:01:45
123 2015-04-10 12:12:17 2015-04-10 13:31:20
123 2015-04-10 12:13:34 2015-04-10 13:37:12
234 2014-12-03 12:12:20 2014-12-03 12:20:23
234 2015-03-03 15:09:44 2015-03-03 16:23:54
我遇到的问题是那些非整理的示例,其中有两个(或更多)请求,后跟两个(或更多)响应。到目前为止,我已经得到了这个:
Select N1.Case_id, N1.Date AS Request_Date, N2.Date as Response_Date
FROM Notes N1
JOIN Notes N2
ON N1.subject = 'Request'
AND N2.date = (
SELECT min(date)
FROM Notes
WHERE Case_Id = N1.Case_Id
AND subject = 'Response'
AND date > N1.date
)
几乎可以正常工作,但正如您从SQL Fiddle here中看到的那样,当您有多个请求后跟多个响应时它会失败 - 它会在第一个响应时失败,而不管它是什么&? #34;权利"按先前的要求。我已经四处搜索了,但我无法弄清楚如何排除已经加入之前的回复。
答案 0 :(得分:0)
这很不愉快,但它似乎适用于您的数据。我必须修复数据中的小故障,因为数据中第7行的值与结果中显示的值不同。
DECLARE @Data TABLE (
Case_Id INT,
[Subject] VARCHAR(50),
[Date] DATETIME);
INSERT INTO @Data SELECT 123, 'Request', '2014-12-03 15:48:02';
INSERT INTO @Data SELECT 123, 'Response', '2014-12-03 16:01:45';
INSERT INTO @Data SELECT 123, 'Response', '2014-12-03 17:32:23';
INSERT INTO @Data SELECT 123, 'Request', '2015-04-10 12:12:17';
INSERT INTO @Data SELECT 123, 'Request', '2015-04-10 12:13:34';
INSERT INTO @Data SELECT 123, 'Response', '2015-04-10 13:31:20';
INSERT INTO @Data SELECT 123, 'Response', '2015-04-10 13:37:12';
INSERT INTO @Data SELECT 234, 'Request', '2014-12-03 12:12:20';
INSERT INTO @Data SELECT 234, 'Response', '2014-12-03 12:20:23';
INSERT INTO @Data SELECT 234, 'Request', '2015-03-03 15:09:44';
INSERT INTO @Data SELECT 234, 'Response', '2015-03-03 16:23:54';
WITH RowIds AS (
SELECT
*,
ROW_NUMBER() OVER (ORDER BY Case_Id, [Date]) AS RowId
FROM
@Data),
Requests AS (
SELECT
Case_Id,
[Date]
FROM
@Data
WHERE
[Subject] = 'Request'),
NextResponse AS (
SELECT
r.Case_Id,
r.[Date] AS Request_Time,
MIN(d.[Date]) AS Response_Time
FROM
Requests r
INNER JOIN @Data d ON d.Case_id = r.Case_id AND d.[Subject] = 'Response' AND d.[Date] > r.[Date]
GROUP BY
r.Case_Id,
r.[Date]),
AssignIds AS (
SELECT
nr.*,
r.RowId
FROM
NextResponse nr
INNER JOIN RowIds r ON r.Case_Id = nr.Case_Id AND r.[Subject] = 'Response' AND r.[Date] = nr.Response_Time),
FindDuplicates AS (
SELECT
RowId
FROM
AssignIds
GROUP BY
RowId
HAVING
COUNT(*) > 1),
ApplyDuplicateOffsets AS (
SELECT
a.Case_Id,
a.Request_Time,
a.Response_Time,
a.RowId,
ROW_NUMBER() OVER (PARTITION BY a.RowId ORDER BY a.Response_Time) AS Offset
FROM
FindDuplicates fd
INNER JOIN AssignIds a ON a.RowId = fd.RowId),
FixDuplicates AS (
SELECT
a.Case_Id,
a.Request_Time,
MIN(CASE WHEN d.RowId IS NULL THEN a.Response_Time ELSE a2.[Date] END) AS Response_Time
FROM
AssignIds a
LEFT JOIN FindDuplicates d ON d.RowId = a.RowId
LEFT JOIN ApplyDuplicateOffsets o ON o.RowId = a.RowId AND o.Request_Time = a.Request_Time
LEFT JOIN RowIds a2 ON a2.Case_Id = a.Case_Id AND a2.RowId >= a.RowId + o.Offset - 1
GROUP BY
a.Case_Id,
a.Request_Time)
SELECT
*
FROM
FixDuplicates
ORDER BY
Case_Id,
Request_Time;
基本上这可以如下工作:
结果如下:
Case_Id Request_Time Response_Time
123 2014-12-03 15:48:02.000 2014-12-03 16:01:45.000
123 2015-04-10 12:12:17.000 2015-04-10 13:31:20.000
123 2015-04-10 12:13:34.000 2015-04-10 13:37:12.000
234 2014-12-03 12:12:20.000 2014-12-03 12:20:23.000
234 2015-03-03 15:09:44.000 2015-03-03 16:23:54.000
这是一个很好的解决方案吗?不是真的,我原本以为这需要某种形式的递归,也许这是解决问题的更好方法吗?