Sql 当存在多个记录时,如何使用最小值和最大值选择记录?
我有两个SQL Server表。第一个表是带有客户编号、名称等的客户表。第二个表包含客户的服务日期。客户可以有多个服务日期。以下是服务日期表的示例:Sql 当存在多个记录时,如何使用最小值和最大值选择记录?,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,我有两个SQL Server表。第一个表是带有客户编号、名称等的客户表。第二个表包含客户的服务日期。客户可以有多个服务日期。以下是服务日期表的示例: custnmbr DateIn DateOut ------------------------------------ 78001 1991-02-10 2001-12-07 78001 2002-08-03 2003-06-17 78001 2006-11-22
custnmbr DateIn DateOut
------------------------------------
78001 1991-02-10 2001-12-07
78001 2002-08-03 2003-06-17
78001 2006-11-22 NULL
我想选择最早的DateIn和最近的DateOut。在上面的示例中,我希望将DateIn返回为1991-02-10,由于客户当前处于活动状态,我希望将DateOut返回为NULL
这是我尝试过的,但没有运气
SELECT
SM.Custnmbr,
CONVERT (VARCHAR(10), MAX(LH.DateIn), 101) AS DateIn,
CONVERT (VARCHAR(10), MAX(LH.DateOut), 101) AS DateOut,
FROM
dbo.toCustomer SM
LEFT OUTER JOIN
dbo.toLocCustHist LH ON SM.CustomerId = LH.CustomerId
GROUP BY
SM.CustNmbr, SM.CustName, LH.LocationId
当我运行查询时,DateIn与1991-02-10是正确的,但是DateOut与2003-06-17是错误的 聚合函数中不考虑
NULL
值,因此需要将NULL
设置为其他值,并且在GROUP BY
语句中不应包含额外的元素:
SELECT
SM.Custnmbr,
CONVERT (VARCHAR(10), MAX(LH.DateIn), 101) AS DateIn,
CONVERT (VARCHAR(10), MAX(ISNULL(LH.DateOut,'2099-01-01'), 101) AS DateOut,
FROM
dbo.toCustomer SM
LEFT OUTER JOIN
dbo.toLocCustHist LH ON SM.CustomerId = LH.CustomerId
GROUP BY
SM.CustNmbr
SQL不考虑空日期大于2003—06-17。您需要将NULL替换为一个遥远的占位符日期,以便MAX()选择它
SELECT SM.Custnmbr,
CONVERT (VARCHAR(10), MAX(LH.DateIn), 101) AS DateIn,
CONVERT (VARCHAR(10), MAX(ISNULL(LH.DateOut,'99991231'), 101) AS DateOut,
FROM dbo.toCustomer SM
LEFT OUTER JOIN dbo.toLocCustHist LH ON SM.CustomerId = LH.CustomerId
GROUP BY SM.CustNmbr, SM.CustName, LH.LocationId
如果要显示当前日期(即
GETDATE()
)而不是9999-12-31,可以使用CASE语句。根据整个查询的外观,group by中的额外元素可能是相关的。例如,如果几个人在多个地点工作,他们在每个地点使用不同的机器,会怎么样。也许我们想要与每个位置相关的数据,但我们不关心位置本身。将客户名称包括在group by中是合适的,但不包括在select中。@Jenn我不确定在什么情况下,将相同的Custnmbr
多次显示关联的MAX()
日期会有帮助,但可能会有这样的情况,这种情况很少见,我认为我的例子并没有完全涵盖这一点。我见过用作摘要的存储过程,它们使用这种技巧。例如,我可能正在撤回一份摘要,该摘要通知IT部门过去一年中已维修的机器数量以及解决问题所需的平均时间。在这种情况下,group by中很可能有不在select中的列。
WITH TEMP AS
(
SELECT SM.Custnmbr AS Custnmbr,
CONVERT (VARCHAR(10), MIN(LH.DateIn), 101) AS DateIn,
CONVERT (VARCHAR(10), MAX(ISNULL(LH.DateOut,'9999-12-12')), 101) AS DateOut,
FROM dbo.toCustomer SM
LEFT OUTER JOIN dbo.toLocCustHist LH ON SM.CustomerId = LH.CustomerId
GROUP BY SM.CustNmbr, SM.CustName, LH.LocationId
)
SELECT Custnmbr,DateIn,
CASE WHEN DateOut='9999-12-12' THEN NULL
ELSE DateOut
END
FROM TEMP;