SQL Server - 使用别名检索唯一行中的两行

时间:2014-05-27 15:13:57

标签: sql sql-server

我有一个表LOGPROCESS,用于存储每个进程的开始/结束,我想进行选择,只使用'作为DateStart' ' as DateEnd'。

这是为每个进程保存日志的方式(ThreadName可能不同):

|ThreadName                         |LEVEL  |Who        | TYPE              | QUERY_STRING                          | DATE
|DevTest                            |INFO   |Tests.Run  | [RECURRING_START] | clientId=300&campId=3130              | 2014-06-27 15:42:57.803
|62013c67-886e-455b-b8aa-ef9139fcc1d4|INFO  |Tests.Send | [RECURRING_END]   | clientId=300&campId=3130&totalSends=0 | 2014-06-27 15:43:58.701

表示START / END的唯一值来自同一进程,是名为CampId的查询字符串的一部分。

我试图执行这样的选择(结束线程的名称是唯一感兴趣的):

select ThreadName,
 (SELECT Date from logprocess  where <what goes here>) as DateStart    
 (SELECT Date fromlogprocess  where <what goes here>) as DateEnd
from logprocess where   

但是我没有找到&lt;&gt;之间的内容。 。

我想要的输出类似于(来自EndProcess的ThreadName,来自开始进程的Date和来自EndProcess的Date):

|ThreadName                           | STARTDATE               | ENDDATE   
|62013c67-886e-455b-b8aa-ef9139fcc1d4 | 2014-06-27 15:42:57.803 | 2014-06-27 15:43:58.701

任何帮助?

提前谢谢。

3 个答案:

答案 0 :(得分:4)

您的挑战是从查询字符串中提取CampID以识别您的行。您可以使用CHARINDEX和SUBSTRING执行此操作,如下所示(我已将逻辑分离为APPLY,以便更清楚地说明正在做什么):

SELECT  CampID = SUBSTRING(QUERY_STRING, StartIndex, EndIndex - StartIndex),
        t.*
FROM    T
-- FIND POSITION OF '&CampID=' IN QUERY_STRING
CROSS APPLY (SELECT StartIndex = CHARINDEX('&campID=', '&' + QUERY_STRING) + 7) si
-- FIND POSITION OF '&' AFTER '$CampID=' IN QUERY_STRING
CROSS APPLY (SELECT EndIndex = CHARINDEX('&', QUERY_STRING + '&', StartIndex + 1)) ei;

获得CampID后,使用条件聚合获取数据非常简单:

SELECT  CampID = SUBSTRING(QUERY_STRING, StartIndex, EndIndex - StartIndex),
        ThreadName = MAX(CASE WHEN [TYPE] = '[RECURRING_END]' THEN ThreadName END),
        StartDate = MAX(CASE WHEN [TYPE] = '[RECURRING_START]' THEN [DATE] END),
        EndDate = MAX(CASE WHEN [TYPE] = '[RECURRING_END]' THEN [DATE] END)
FROM    T t
CROSS APPLY (SELECT StartIndex = CHARINDEX('&campID=', '&' + QUERY_STRING) + 7) si
CROSS APPLY (SELECT EndIndex = CHARINDEX('&', QUERY_STRING + '&', StartIndex + 1)) ei
GROUP BY SUBSTRING(QUERY_STRING, StartIndex, EndIndex - StartIndex);

<强> Example on SQL Fiddle

答案 1 :(得分:2)

嗯,它不漂亮:

SELECT b.ThreadName
      ,a.[date] as StartDate
      ,b.[date] as EndDate
FROM logprocess a 
LEFT JOIN logprocess b
  ON SUBSTRING(a.query_string
              ,PATINDEX('%campId=%', a.query_string)+7
              ,LEN(a.query_string)-(PATINDEX('%campId=%', a.query_string)+6))
   = SUBSTRING(b.query_string
              ,PATINDEX('%campId=%', a.query_string)+7
              ,LEN(a.query_string)-(PATINDEX('%campId=%', a.query_string)+6))
WHERE a.type = '[RECURRING_START]'
  AND b.type = '[RECURRING_END]'

SQLFiddle

只要campId始终是[RECURRING_START]行中的最后一个变量,然后出现在[RECURRING_END]行的相同位置,这就应该有效。我会想象它的速度非常慢。

答案 2 :(得分:0)

您可以进行连接,以便为同一字段设置不同的Where子句,并使用公共字段链接它们。

select a.<commonField>, a.Date as DateStart, b.Date as DateEnd
from logprocess a
inner join logprocess b on a.<commonField>= b.<commonField>
where a.Type = "RECURRING_START"
and b.Type = "RECURRING_END"
相关问题