Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/git/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 当存在多个记录时,如何使用最小值和最大值选择记录?_Sql_Sql Server_Sql Server 2008 - Fatal编程技术网

Sql 当存在多个记录时,如何使用最小值和最大值选择记录?

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

我有两个SQL Server表。第一个表是带有客户编号、名称等的客户表。第二个表包含客户的服务日期。客户可以有多个服务日期。以下是服务日期表的示例:

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;