我刚开始学习SQL。我写了以下内容:
DECLARE @DateFrom Date = '01-Jan-2014', @DateTo Date = '31-Dec-2014'
SELECT TotalCalls, UniqueCalls, TotalEmails, UniqueEmails, AgentsContacted, Instructed FROM
( SELECT *,
(SELECT YEAR(EventDate)) AS year,
(SELECT COUNT(*) FROM Events JOIN dbo.ContactType
ON EventContactType=ContactTypeID
WHERE ContactTypeName = 'Call' AND EventDate >= @DateFrom AND EventDate <= @DateTo) AS TotalCalls,
(SELECT COUNT(Distinct EventAgentID) FROM Events JOIN dbo.ContactType
ON EventContactType=ContactTypeID
WHERE ContactTypeName = 'Call' AND EventDate >= @DateFrom AND EventDate <= @DateTo) AS UniqueCalls,
(SELECT COUNT(*) FROM Events JOIN dbo.ContactType
ON EventContactType=ContactTypeID
WHERE ContactTypeName = 'Email' AND EventDate >= @DateFrom AND EventDate <= @DateTo) AS TotalEmails,
(SELECT COUNT(Distinct EventAgentID) FROM Events JOIN dbo.ContactType
ON EventContactType=ContactTypeID
WHERE ContactTypeName = 'Email' AND EventDate >= @DateFrom AND EventDate <= @DateTo) AS UniqueEmails,
(SELECT COUNT(DISTINCT EventAgentID)
FROM Events
JOIN dbo.ContactType
ON EventContactType=ContactTypeID
LEFT JOIN (SELECT AgentID, (SELECT CASE WHEN AgentDateOfRecentInstruction Is Null OR
AgentDateOfRecentInstruction < DATEADD(month, -12, @DateFrom) --for sp change get date to @FromDate
THEN 'NO' ELSE 'YES' END) AS InstructedWithinPastYear FROM Agents) ti
ON Events.EventAgentID=ti.AgentID
WHERE EventToFrom='1'
AND (ContactTypeName = 'Email' OR ContactTypeName = 'Call')
AND InstructedWithinPastYear = 'NO'
AND (EventDate >= @DateFrom AND EventDate <= @DateTo)) AS AgentsContacted,
(SELECT COUNT(DISTINCT EventAgentID)
FROM Events
Join dbo.AGents
ON EventAgentID=AgentID
JOIN dbo.ContactType
ON EventContactType=ContactTypeID
LEFT JOIN (SELECT AgentID, (SELECT CASE WHEN AgentDateOfRecentInstruction Is Null OR
AgentDateOfFirstIntsruction < @DateFrom --for sp change get date to @FromDate
THEN 'NO' ELSE 'YES' END) AS InstructedWithinPastYear FROM Agents) ti
ON Events.EventAgentID=ti.AgentID
WHERE EventToFrom='1'
AND (ContactTypeName = 'Email' OR ContactTypeName = 'Call')
AND (AgentDateOfRecentInstruction <= @DateTo AND AgentDateOfRecentInstruction >= @DateFrom)
AND (EventDate >= @DateFrom AND EventDate <= @DateTo)) AS Instructed
FROM Events
JOIN dbo.ContactType
ON EventContactType=ContactTypeID
Join dbo.AGents
ON EventAgentID=AgentID
)
as s
PIVOT (count(EventAgentID) FOR year
IN ([2013],[2014]) ) pvt
返回数千行:
TotalCalls | UniqueCalls | TotalEmails | UniqueEmails | AgentsContacted | Instructed 169 | 106 | 202 | 125 | 24 | 15 169 | 106 | 202 | 125 | 24 | 15 169 | 106 | 202 | 125 | 24 | 15
我想要它返回:
Year | TotalCalls | UniqueCalls | TotalEmails | UniqueEmails | AgentsContacted 2014 | 169 | 106 | 202 | 125 | 24 2013 | 69 | 68 | 112 | 86 | 13
我很确定我在这里犯了一些错误,但我无法简洁地写出我的问题,以便从搜索中找出解决方法。
(注意:我在编写程序时暂时存在局部变量)
答案 0 :(得分:2)
您可以通过将所有内容放入一个查询语句而不是SELECT语句中的一系列单个查询来大大简化此查询。现在,你有&#34; SELECT (SELECT Blah1FROM X), (SELECT Blah2 FROM X)
&#34;在那里你可以轻松地写下#34; SELECT Blah1, Blah2 FROM X
&#34;有点创造力。
您的代码中存在一些导致问题的基本缺陷 - 您正在聚合每个SELECT查询中的每一行,因此您返回的数据实际上是所有记录中的计数,不是你想要的那一年。此外,您从不对结果进行分组(查找GROUP BY
语句),以便您返回数千行,每个详细记录一行,而不是每年我想要的单行。
考虑编写更类似于以下内容的内容,它使用GROUP BY对单个查询进行聚合。
DECLARE @DateFrom Date = '01-Jan-2014', @DateTo Date = '31-Dec-2014'
SELECT
YEAR(EventDate) AS [Year],
COUNT(CASE WHEN ContactTypeName = 'Call' THEN EventAgentID END) AS TotalCalls, -- You might need the "EventDate >= @DateFrom AND EventDate <= @DateTo" as part of this CASE statement
COUNT(DISTINCT CASE WHEN ContactTypeName = 'Call' THEN EventAgentID END) AS UniqueCalls,
COUNT(CASE WHEN ContactTypeName = 'Email' THEN EventAgentID END) AS TotalEmails,
COUNT(DISTINCT CASE WHEN ContactTypeName = 'Email' THEN EventAgentID END) AS UniqueEmails,
COUNT(DISTINCT
CASE
WHEN
EventToFrom='1' AND
ContactTypeName IN ('Call', 'Email') AND
(AgentDateOfRecentInstruction IS NULL OR AgentDateOfRecentInstruction < DATEADD(month, -12, @DateFrom)) AND
(EventDate >= @DateFrom AND EventDate <= @DateTo)
THEN EventAgentID
END) AS AgentsContacted,
COUNT(DISTINCT
CASE
WHEN
EventToFrom='1' AND
ContactTypeName IN ('Call', 'Email') AND
AgentDateOfRecentInstruction <= @DateTo AND AgentDateOfRecentInstruction >= @DateFromAND
(EventDate >= @DateFrom AND EventDate <= @DateTo)
THEN EventAgentID
END) AS AgentsContacted
FROM
dbo.Events
INNER JOIN
dbo.ContactType ON
EventContactType=ContactTypeID
INNER JOIN
dbo.Agents ON
EventAgentID=AgentID
GROUP BY YEAR(EventDate)
缺少任何样本数据甚至是模板,我无法保证此转换无需任何调整即可 - 您可能必须使用此代码,检查拼写或语法错误,然后转到通过每个陈述,以确保它实际上做你想要的。但是,它应该让你开始。