SELECT语句中带有WHERE子句的嵌套COUNT

时间:2016-05-28 14:48:58

标签: sql sql-server-2008

我是SQL脚本的新手,我试图从表格中获取一些计数,其中我计算3种不同的方式,COUNT(1)不是问题,但接下来的两个计数非常慢。

WHERE子句中使用的所有列都有单独的索引,但仍然很慢。是否有更容易和更好的方法来执行这些COUNT?

在下面的代码中,我希望在每个父级SELECT GROUP BY时间戳上获得所有唯一的CustomerID:

(SELECT COUNT(DISTINCT al2.CustomerID) FROM ActionLog al2
WHERE CONVERT(VARCHAR(10),al2.Timestamp,110) = CONVERT(VARCHAR(10),al1.Timestamp,110) and al2.ActionTypeID = al1.ActionTypeID and al2.CampaignID = al1.CampaignID and al2.EventID = al1.EventID and CASE WHEN CHARINDEX('?', al2.URL) > 0 THEN LEFT(URL, CHARINDEX('?', al2.URL)-1) ELSE URL END = CASE WHEN CHARINDEX('?', al1.URL) > 0 THEN LEFT(URL, CHARINDEX('?', al1.URL)-1) ELSE URL END
AND al2.Timestamp BETWEEN DATEADD(dd, DATEDIFF(dd, 0, GETDATE()),-7) AND DATEADD(dd, DATEDIFF(dd, 0, GETDATE()),0)) as Count_Total_DayUnique

下一个我想得到之前未成为父SELECT GROUP BY子句一部分的所有新的唯一CustomerID:

(SELECT COUNT(DISTINCT al3.CustomerID) FROM ActionLog al3
WHERE al3.ActionTypeID = al1.ActionTypeID and al3.CampaignID = al1.CampaignID and al3.EventID = al1.EventID and CASE WHEN CHARINDEX('?', al3.URL) > 0 THEN LEFT(URL, CHARINDEX('?', al3.URL)-1) ELSE URL END = CASE WHEN CHARINDEX('?', al1.URL) > 0 THEN LEFT(URL, CHARINDEX('?', al1.URL)-1) ELSE URL END
and al3.CustomerID not in (SELECT COUNT(DISTINCT al4.CustomerID) FROM ActionLog al4
WHERE al4.ActionTypeID = al1.ActionTypeID and al4.CampaignID = al1.CampaignID and al4.EventID = al1.EventID and CASE WHEN CHARINDEX('?', al4.URL) > 0 THEN LEFT(URL, CHARINDEX('?', al3.URL)-1) ELSE URL END = CASE WHEN CHARINDEX('?', al1.URL) > 0 THEN LEFT(URL, CHARINDEX('?', al1.URL)-1) ELSE URL END
AND al4.Timestamp > DATEADD(dd, -1, CONVERT(VARCHAR(10),al1.Timestamp,110)))) as Count_Total_UniqueOnEvent

请参阅下面的整个脚本:

  SELECT CONVERT(VARCHAR(10),Timestamp,110) as Timestamp
  ,ActivityTypeID
  ,ActionTypeID
  ,CampaignID
  ,EventID
  ,COUNT(1) as Count_Total_Day
  ,(SELECT COUNT(DISTINCT al2.CustomerID) FROM ActionLog al2
    WHERE CONVERT(VARCHAR(10),al2.Timestamp,110) = CONVERT(VARCHAR(10),al1.Timestamp,110) and al2.ActionTypeID = al1.ActionTypeID and al2.CampaignID = al1.CampaignID and al2.EventID = al1.EventID and CASE WHEN CHARINDEX('?', al2.URL) > 0 THEN LEFT(URL, CHARINDEX('?', al2.URL)-1) ELSE URL END = CASE WHEN CHARINDEX('?', al1.URL) > 0 THEN LEFT(URL, CHARINDEX('?', al1.URL)-1) ELSE URL END
    AND al2.Timestamp BETWEEN DATEADD(dd, DATEDIFF(dd, 0, GETDATE()),-7) AND DATEADD(dd, DATEDIFF(dd, 0, GETDATE()),0)) as Count_Total_DayUnique
  ,(SELECT COUNT(DISTINCT al3.CustomerID) FROM ActionLog al3
    WHERE al3.ActionTypeID = al1.ActionTypeID and al3.CampaignID = al1.CampaignID and al3.EventID = al1.EventID and CASE WHEN CHARINDEX('?', al3.URL) > 0 THEN LEFT(URL, CHARINDEX('?', al3.URL)-1) ELSE URL END = CASE WHEN CHARINDEX('?', al1.URL) > 0 THEN LEFT(URL, CHARINDEX('?', al1.URL)-1) ELSE URL END
    and al3.CustomerID not in (SELECT COUNT(DISTINCT al4.CustomerID) FROM ActionLog al4
    WHERE al4.ActionTypeID = al1.ActionTypeID and al4.CampaignID = al1.CampaignID and al4.EventID = al1.EventID and CASE WHEN CHARINDEX('?', al4.URL) > 0 THEN LEFT(URL, CHARINDEX('?', al3.URL)-1) ELSE URL END = CASE WHEN CHARINDEX('?', al1.URL) > 0 THEN LEFT(URL, CHARINDEX('?', al1.URL)-1) ELSE URL END
    AND al4.Timestamp > DATEADD(dd, -1, CONVERT(VARCHAR(10),al1.Timestamp,110)))) as Count_Total_UniqueOnEvent
  ,ReportTag
  ,CASE WHEN CHARINDEX('?', URL) > 0 THEN LEFT(URL, CHARINDEX('?', URL)-1) ELSE URL END as URL
  ,TemplateID
  FROM ActionLog al1
  WHERE Timestamp BETWEEN DATEADD(dd, DATEDIFF(dd, 0, GETDATE()),-7) AND DATEADD(dd, DATEDIFF(dd, 0, GETDATE()),0)
  GROUP BY CONVERT(VARCHAR(10),Timestamp,110),ActivityTypeID,ActionTypeID,CampaignID,EventID,ReportTag,URL,TemplateID

我将尝试为您提供有关数据库,样本数据和预期结果的背景信息。

数据库结构:

[dbo].[ActionLog](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Timestamp] [datetime] NULL CONSTRAINT [DF_ActionLog]  DEFAULT (getdate()),
[CustomerID] [int] NULL,
[ActivityTypeID] [int] NULL,
[ActionTypeID] [int] NULL,
[CampaignID] [int] NULL,
[EventID] [int] NULL,
[ReportTag] [varchar](500) NULL,
[URL] [varchar](500) NULL,
[TemplateID] [int] NULL,
)

样品:

ID  Timestamp   CustomerID  ActivityTypeID  ActionTypeID    CampaignID  EventID ReportTag   URL TemplateID
1   2014-09-24 11:55:27.900 1   1   12  35  68  NULL    NULL    NULL
2   2014-09-24 12:58:26.710 2   1   12  35  68  NULL    NULL    NULL
3   2014-09-24 13:54:34.993 2   1   12  35  68  NULL    NULL    NULL
4   2014-09-24 16:35:33.810 4   1   12  35  68  NULL    NULL    NULL
5   2014-09-24 16:53:17.623 1   1   12  35  68  NULL    NULL    NULL
6   2014-09-25 20:36:30.190 1   1   12  35  68  NULL    NULL    NULL
7   2014-09-25 20:36:33.050 4   1   12  35  68  NULL    NULL    NULL
8   2014-09-25 23:35:38.520 3   1   12  35  68  NULL    NULL    NULL
9   2014-09-25 08:35:15.247 4   1   12  35  68  NULL    NULL    NULL
10  2014-09-25 08:36:11.363 6   1   12  35  68  NULL    NULL    NULL
11  2014-09-26 11:23:58.223 1   1   12  35  68  NULL    NULL    NULL
12  2014-09-26 11:55:12.640 2   1   12  35  68  NULL    NULL    NULL
13  2014-09-26 12:03:28.563 6   1   12  35  68  NULL    NULL    NULL
14  2014-09-26 12:39:53.003 7   1   12  35  68  NULL    NULL    NULL
15  2014-09-26 15:55:55.843 8   1   12  35  68  NULL    NULL    NULL
16  2014-09-27 15:55:55.890 1   1   12  35  68  NULL    NULL    NULL
17  2014-09-27 16:22:05.540 3   1   12  35  68  NULL    NULL    NULL
18  2014-09-27 17:34:43.093 8   1   12  35  68  NULL    NULL    NULL
19  2014-09-27 09:40:23.743 9   1   12  35  68  NULL    NULL    NULL
20  2014-09-27 10:08:50.240 11  1   12  35  68  NULL    NULL    NULL
21  2014-09-28 10:12:37.330 11  1   12  35  68  NULL    NULL    NULL
22  2014-09-28 11:22:26.413 12  1   12  35  68  NULL    NULL    NULL
23  2014-09-28 11:23:06.520 13  1   12  35  68  NULL    NULL    NULL
24  2014-09-28 11:52:26.757 14  1   12  35  68  NULL    NULL    NULL
25  2014-09-28 13:05:13.850 15  1   12  35  68  NULL    NULL    NULL
26  2014-09-29 13:05:24.900 16  1   12  35  68  NULL    NULL    NULL
27  2014-09-29 13:06:07.017 16  1   12  35  68  NULL    NULL    NULL
28  2014-09-29 13:07:26.993 14  1   12  35  68  NULL    NULL    NULL
29  2014-09-29 14:13:04.893 13  1   12  35  68  NULL    NULL    NULL
30  2014-09-29 19:54:11.350 12  1   12  35  68  NULL    NULL    NULL

我的预期结果:

 Timestamp  ActivityTypeID  ActionTypeID    CampaignID  EventID Count   Count_Total_DayUnique   Count_Total_UniqueOnEvent   Report  Url TemplateID
2014-09-24  1   12  35  68  5   3   3   NULL    NULL    NULL
2014-09-25  1   12  35  68  5   4   2   NULL    NULL    NULL
2014-09-26  1   12  35  68  5   5   2   NULL    NULL    NULL
2014-09-27  1   12  35  68  5   5   3   NULL    NULL    NULL
2014-09-28  1   12  35  68  5   5   4   NULL    NULL    NULL
2014-09-29  1   12  35  68  5   4   1   NULL    NULL    NULL

我真的希望有人可以帮助我。

提前致谢

1 个答案:

答案 0 :(得分:1)

对于此子查询:

(SELECT COUNT(DISTINCT al2.CustomerID)
 FROM ActionLog al2
 WHERE CONVERT(VARCHAR(10),al2.Timestamp,110) = CONVERT(VARCHAR(10),al1.Timestamp,110) and
       al2.ActionTypeID = al1.ActionTypeID and
       al2.CampaignID = al1.CampaignID and
       al2.EventID = al1.EventID and
       (CASE WHEN CHARINDEX('?', al2.URL) > 0
             THEN LEFT(URL, CHARINDEX('?', al2.URL)-1)
             ELSE URL
        END) = (CASE WHEN CHARINDEX('?', al1.URL) > 0 
                     THEN LEFT(URL, CHARINDEX('?', al1.URL)-1)
                     ELSE URL
                END) AND
       al2.Timestamp BETWEEN DATEADD(day, DATEDIFF(dd, 0, GETDATE()),-7) AND DATEADD(day, DATEDIFF(dd, 0, GETDATE()),0)
) as Count_Total_DayUnique

这很复杂。但您可以从ActionLog(ActionTypeId, CampaignId, EventId, TimeStamp, url, CustomerId)上的索引开始。这应该涵盖子查询,因此只有索引才会用于子查询。