【问题标题】:SQL Server Compiling and Calculating Data from Multiple TablesSQL Server 从多个表编译和计算数据
【发布时间】:2013-03-21 21:07:26
【问题描述】:

我正在尝试找出我数据库中的订阅者在一天中打开电子邮件最多的时间。

我有一个包含一堆订阅者 ID 的表,我还有另一个表,其中电子邮件打开记录映射到一个表,该表存储已发送的电子邮件,然后映射到特定的订阅者 ID。

所以我的基本愿望是获得一个表格输出,其中每一行都是一个特定的订阅者(订阅者 ID)以及他们打开最多电子邮件的时间。所以我需要先检查每个订阅者 ID,然后我猜想创建一个临时表,每一行是一个不同的小时,与他们在该小时打开的电子邮件数量相关联。然后我需要选择 Max 以从该临时表中获取最大行,然后我需要将其放入我的输出表中,并为下一个订阅者重复。

我只关心一天中的时间。我不在乎月份、年份或时间。我只是想知道人们在一天中的哪个时间点最常打开电子邮件。

我一直在尝试使用 CTE 和 while 循环,但无济于事。任何帮助将不胜感激。

这是(最小化的)结构:

表:订阅者

|订阅者 ID |姓氏 |名字 |
| 9999999999 |史密斯 |约翰 |

表:SentEmail

| message_id |订阅者 ID |
| 9028340 | 9999999999 |

表:打开电子邮件

| open_id | message_id | dtoped |
| 9923489 | 9028340 | '2011-11-22 15:53:02.157' |

我的目标是这样的输出表(最后一列是不必要的),每个subscriber_id 在列表中都是唯一的:

|订阅者 ID |开放时间 |打开次数 |
| 999999999 | 10 | 32 |

【问题讨论】:

  • 欢迎来到 SO。解决此问题的最佳方法是使用 SQLFiddle (sqlfiddle.com) 创建您的数据定义以及您迄今为止尝试过的内容 (DML)。
  • 尝试加入这些表,然后按订阅者 ID、DATEPART(HH,opendate) 分组,然后依靠电子邮件 ID 或其他东西。如果您需要查询代码,则需要共享您的架构和一些示例数据。

标签: sql sql-server sql-server-2005 sql-server-2008-r2


【解决方案1】:

我做了一些假设,因为没有包含结构。

这是我使用的结构。

CREATE TABLE Subscriber (
    Id int not null identity(1,1),
    SubscriberId varchar(50)
    )
CREATE TABLE EmailOpened (
    OpenDate DateTime,
    EmailId int
    )
CREATE TABLE Emails (
    EmailId int not null identity(1,1),
    SubscriberId varchar(50),
    EmailText varchar(max)
)
GO

这是我最终得到的查询。

WITH OpenedByHour AS (
    SELECT 
        SubscriberId,
        DATEPART(YEAR, OpenDate) AS OpenYear,
        DATEPART(DAYOFYEAR, OpenDate) AS OpenDOY,
        DATEPART(HOUR, OpenDate) AS OpenHour,
        COUNT(1) AS OpenCount
    FROM Emails
    JOIN EmailOpened
        ON Emails.EmailId = EmailOpened.EmailId
    GROUP BY 
        SubscriberId,
        DATEPART(YEAR, OpenDate),
        DATEPART(DAYOFYEAR, OpenDate),
        DATEPART(HOUR, OpenDate)
    ),
    MaxOpenedByHour AS (
    SELECT
        SubscriberId,
        OpenYear,
        OpenDOY,
        OpenHour,
        OpenCount,
        Row_Number() Over (Partition By SubscriberId
                Order By OpenCount Desc) AS MaxRow
    FROM OpenedByHour
    )
SELECT SubscriberId,
    OpenYear,
    OpenDOY,
    OpenHour,
    OpenCount
FROM MaxOpenedByHour
WHERE MaxRow = 1

【讨论】:

  • 这将返回所有订阅者 ID 的列表以及他们在数据库中的每小时计数。所以我得到每个订阅者多行
  • 我进行了更改。立即尝试。
  • 这看起来很有希望,但我得到了奇怪的结果,例如 0000000Jay AND ="00919322 作为订阅者 ID。订阅者 ID 存储为 varchar,这是导致问题的原因吗?
  • 当我使用 WHERE 子句将其限制为一个 id 时,它可以完美运行
  • 您确定您的订阅者 ID 表中没有错误数据吗? Varchar 不应该有所作为。实际上,如果你看,我假设。很多时候,尽管您会在这样的列中获得一些不良数据。在你做这样的总结报告之前,你永远不会注意到它。在您的订阅者表中查询 0000000Jay 的订阅者 ID,看看它是否出现。
【解决方案2】:

您必须弄清楚如何使用正确的列来调整它,以及由于未提供架构而不能解决的问题...

With    orderedHourly As
(
        Select  SubscriberID, 
                Convert(Date,OpenDateTime) OpenDate, 
                Hour(OpenDateTime) OpenHour, 
                Row_Number() Over (Partition By SubscriberID, Convert(Date,OpenDateTime) Order By Count(1) Desc) As HourPriority
        From    subscriber s
        Join    email e
                On  s.subscriberID = e.subscriberID
        Group   By SubscriberID, Convert(Date,OpenDateTime), Hour(OpenDateTime)
)
Select  SubScriberID, OpenDate, OpenHour
From    orderHourly
Where   HourPriority = 1

【讨论】:

  • 它看起来有效,但每个subscriber_id 我得到不止一行
  • 这将给您每天一排。您是否想要在很长一段时间内活动最多的小时?
  • 看起来你得到了一个适合你的答案,所以不用担心。很高兴你明白了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-09
  • 2012-01-25
  • 1970-01-01
  • 2017-03-23
  • 2015-01-04
相关资源
最近更新 更多