【问题标题】:AVG(DATEDIFF(d,Tabl1.date1,MIN(Table2.date1))) T-SQLAVG(DATEDIFF(d,Table1.date1,MIN(Table2.date1))) T-SQL
【发布时间】:2013-04-22 20:02:42
【问题描述】:

我正在尝试创建一个报告以提供来自 SQL Server 数据库的数据。我有 3 张我感兴趣的表格,客户、推荐人、约会。客户可以有 1.* 推荐,推荐可以有 0.* 预约。

在我的报告中,我想显示从收到推荐到第一次预约的平均时间。

我在我的存储过程中尝试上述方法,但收到“无法对包含聚合或子查询的表达式执行聚合函数。”

有没有一种巧妙的方法可以在没有子查询的情况下让它工作?

编辑下面的粗略表结构。

客户 ClientID INT IIDENTITY (pk) 名字 VARCHAR(50) 姓 VARCHAR(50) 出生日期时间

推荐 ReferralID INT IDENTITY (pk) ClientID INT (fk) ReferralRequestReceivedDate DATETIME OrgaisationAreaId INT (fk)

约会 AppintmentID INT IDENTITY (pk) 推荐人 ID INT(fk) 约会日期日期时间 出勤类型 ID INT (fk) AppointmentTypeID INT (fk)

出勤类型 出勤类型ID INT IDENTITY (pk) 名称 VARCHAR(50)

约会类型 AppointmentTypeID INT IDENTITY (pk) 名称 VARCHAR(50)

组织区域 OrgaisationAreaId INT IDENTITY(pk) 名称 VARCHAR(50)

我现有的 proc 有按年龄和出席类型出席的约会计数,如下所示...

SELECT OA.Name, 
COUNT(CASE WHEN AppointmentTypeId IN(1,3) 
               AND AppointmentDate BETWEEN '27 Jan 2013' AND '13 Apr 2013' 
               THEN AppointmentId END) AS AppsBooked,
AVG(DATEDIFF(d, ReferralRequestReceivedDate, MIN(A.AppointmentDate))) 
AS AvgAllocationWaitTime

FROM OrganisationAreas OA
LEFT OUTER JOIN Clients C
    ON OA.OrganisationAreaId = C.OrganisationAreaId
LEFT OUTER JOIN IaptReferrals R 
    ON C.ClientId = R.ClientId
LEFT OUTER JOIN IaptAppointments A
    ON R.IaptReferralId = A.Referral_IaptReferralId

GROUP BY OA.OrganisationAreaId, OA.Name

【问题讨论】:

  • 这些表的结构是什么?什么键将它们联系在一起?
  • 你为什么要这个没有子查询的工作?

标签: sql tsql aggregate-functions average


【解决方案1】:

如果不使用子查询或 cte,我想不出办法。 但如果你对子查询没问题,试试这个

SELECT OA.Name, 
COUNT(CASE WHEN 
            AppointmentTypeId IN(1,3) AND AppointmentDate BETWEEN '27 Jan 2013' AND '13 Apr 2013' THEN AppointmentId 
      END) AS AppsBooked,
AVG(DATEDIFF(d, ReferralRequestReceivedDate, sq.MinAppointmentDate)) AS AvgAllocationWaitTime
FROM OrganisationAreas OA
LEFT OUTER JOIN
(
    SELECT  C.OrganisationAreaId, MIN(A.AppointmentDate) MinAppointmentDate 
    FROM IaptAppointments A
    LEFT OUTER JOIN IaptReferrals R ON R.IaptReferralId = A.Referral_IaptReferralId
    LEFT OUTER JOIN Clients C ON C.ClientId = R.ClientId 
    GROUP BY C.OrganisationAreaId
) sq ON sq.OrganisationAreaId = OA.OrganisationAreaId
GROUP BY OA.OrganisationAreaId, OA.Name

或cte版本:

;WITH cte AS 
(
    SELECT C.OrganisationAreaId, MIN(A.AppointmentDate) MinAppointmentDate 
    FROM IaptAppointments A
    LEFT OUTER JOIN IaptReferrals R ON R.IaptReferralId = A.Referral_IaptReferralId
    LEFT OUTER JOIN Clients C ON C.ClientId = R.ClientId
    GROUP BY C.OrganisationAreaId
)
SELECT OA.Name, 
COUNT(CASE WHEN 
            AppointmentTypeId IN(1,3) AND AppointmentDate BETWEEN '27 Jan 2013' AND '13 Apr 2013' THEN AppointmentId 
      END) AS AppsBooked,
AVG(DATEDIFF(d, ReferralRequestReceivedDate, cte.MinAppointmentDate)) AS AvgAllocationWaitTime
FROM OrganisationAreas OA
LEFT OUTER JOIN cte ON cte.OrganisationAreaId = OA.OrganisationAreaId
GROUP BY OA.OrganisationAreaId, OA.Name

【讨论】:

  • 顶级建议 Ethan。干杯。用过 CTE 版本,很喜欢。
【解决方案2】:

你有这个:

SELECT OA.Name, 
COUNT(CASE WHEN AppointmentTypeId IN(1,3) 
               AND AppointmentDate BETWEEN '27 Jan 2013' AND '13 Apr 2013' 
               THEN AppointmentId END) AS AppsBooked,
AVG(DATEDIFF(d, ReferralRequestReceivedDate, MIN(A.AppointmentDate))) 
AS AvgAllocationWaitTime

FROM OrganisationAreas OA
LEFT OUTER JOIN Clients C
    ON OA.OrganisationAreaId = C.OrganisationAreaId
LEFT OUTER JOIN IaptReferrals R 
    ON C.ClientId = R.ClientId
LEFT OUTER JOIN IaptAppointments A
    ON R.IaptReferralId = A.Referral_IaptReferralId

GROUP BY OA.OrganisationAreaId, OA.Name

让我们看看如何改进它。首先,如果您想要推荐日期和第一次约会之间的平均时间,您需要内部联接,而不是外部联接。其次,您有一个没有 else 条件的 case 构造。第三,您对已预订的约会有所了解,这似乎无关紧要。最后,您收到了错误语法的错误消息。

要修复最后一个错误,请将最短约会日期移至子查询。这将使您的查询看起来像这样:

select oa.name
, avg(datediff(d, ReferralRequestReceivedDate, MinAppointmentDate)) 
AvgAllocationWaitTime

from OrganisationAreas oa 
JOIN Clients C
    ON OA.OrganisationAreaId = C.OrganisationAreaId
JOIN IaptReferrals R 
    ON C.ClientId = R.ClientId
join (
select referral_iaptReferralId refid
, min(appointmentdate) MinAppointmentDate
from IaptAppointments
where clause goes here
group by referral_iaptReferralId
) temp on refid = r.iaptReferralId

where clause goes here

保持这个基本结构。如果您还想要预约计数,请尽量保持简单。

【讨论】:

  • 嗨,丹。谢谢您的帮助。我使用了外部联接,因为我仍然希望无论是否分配了任何引用都返回该区域,以便我可以显示零计数。为帮助的人干杯。我会尝试了解 CTE 功能,看起来很强大。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多