我已经尝试了在您的网站上找到的几种解决方案,但没有什么能与我需要的完全匹配。在SQL Server中,我需要使用GROUP BY
查询进行多表连接,并仅返回每个组中的TOP 1
行。以下是返回所需记录的基本代码,但将返回符合条件的所有记录:
SELECT MIN(Maintenance_Log.Log_StartDate) As MaintDate
, Manufacturer.Manufacturer_Name
, GL_Inventory.Inventory_Model
, GL_Inventory.Inventory_SerialNr
, Maintenance_Log.Event_ID
, Maintenance_Log.Inventory_ID
FROM Maintenance_Log
INNER JOIN GL_Inventory ON Maintenance_Log.Inventory_ID = GL_Inventory.Inventory_ID
INNER JOIN Manufacturer ON GL_Inventory.Manufacturer_ID = Manufacturer.Manufacturer_ID
WHERE Maintenance_Log.Owner_ID = @OwnerID
AND Maintenance_Log.Log_CompletedDate Is Null
GROUP BY Maintenance_Log.Inventory_ID
, Maintenance_Log.Log_StartDate
, Manufacturer.Manufacturer_Name
, GL_Inventory.Inventory_Model
, GL_Inventory.Inventory_SerialNr
, Maintenance_Log.Event_ID
返回的结果是:
2016-06-30 09:00:00.000 GLOCK G19 Gen 4 ABDE1234 2 6
2016-07-28 09:00:00.000 GLOCK G19 Gen 4 ABDE1234 3 6
2016-08-25 09:00:00.000 GLOCK G19 Gen 4 ABDE1234 4 6
2016-09-29 09:00:00.000 GLOCK G19 Gen 4 ABDE1234 5 6
2016-10-27 09:00:00.000 GLOCK G19 Gen 4 ABDE1234 6 6
2016-11-24 09:00:00.000 GLOCK G19 Gen 4 ABDE1234 7 6
2016-12-29 09:00:00.000 GLOCK G19 Gen 4 ABDE1234 8 6
2016-07-01 09:00:00.000 S&W 642 WQ32De45 9 7
2016-08-05 09:00:00.000 S&W 642 WQ32De45 10 7
2016-09-02 09:00:00.000 S&W 642 WQ32De45 11 7
2016-10-07 09:00:00.000 S&W 642 WQ32De45 12 7
2016-11-04 09:00:00.000 S&W 642 WQ32De45 13 7
2016-12-02 09:00:00.000 S&W 642 WQ32De45 14 7
我想根据行中的最后一位数字{@ 1}}返回每个组中的 TOP 1 行,而不是所有符合条件的行。
答案 0 :(得分:0)
这是您的查询,使用表别名进行格式化和简化:
SELECT MIN(l.Log_StartDate) As MaintDate, m.Manufacturer_Name,
i.Inventory_Model, i.Inventory_SerialNr, l.Event_ID, l.Inventory_ID
FROM Maintenance_Log l INNER JOIN
GL_Inventory i
ON l.Inventory_ID = i.Inventory_ID INNER JOIN
Manufacturer m
ON i.Manufacturer_ID = m.Manufacturer_ID)
WHERE l.Owner_ID = @OwnerID AND l.Log_CompletedDate Is Null
GROUP BY l.Log_StartDate, m.Manufacturer_Name, i.Inventory_Model,
i.Inventory_SerialNr, l.Event_ID, l.Inventory_ID ;
首先,我注意到Log_StartDate
位于GROUP BY
和MIN()
的参数中。所以,我想知道这是否能解决你的问题:
SELECT MIN(l.Log_StartDate) As MaintDate, m.Manufacturer_Name,
i.Inventory_Model, i.Inventory_SerialNr, l.Event_ID, l.Inventory_ID
FROM Maintenance_Log l INNER JOIN
GL_Inventory i
ON l.Inventory_ID = i.Inventory_ID INNER JOIN
Manufacturer m
ON i.Manufacturer_ID = m.Manufacturer_ID)
WHERE l.Owner_ID = @OwnerID AND l.Log_CompletedDate Is Null
GROUP BY m.Manufacturer_Name, i.Inventory_Model,
i.Inventory_SerialNr, l.Event_ID, l.Inventory_ID ;
如果您仍然想要最大inventory_id的一行,那么您可以使用窗口函数:
WITH t as (
SELECT MIN(l.Log_StartDate) As MaintDate, m.Manufacturer_Name,
i.Inventory_Model, i.Inventory_SerialNr, l.Event_ID, l.Inventory_ID ,
ROW_NUMBER() OVER (PARTITION BY m.Manufacturer_Name, i.Inventory_Model, i.Inventory_SerialNr, l.Event_ID
ORDER BY l.Inventory_ID -- Do you want this ASC or DESC ?
) as seqnum
FROM Maintenance_Log l INNER JOIN
GL_Inventory i
ON l.Inventory_ID = i.Inventory_ID INNER JOIN
Manufacturer m
ON i.Manufacturer_ID = m.Manufacturer_ID)
WHERE l.Owner_ID = @OwnerID AND l.Log_CompletedDate Is Null
GROUP BY m.Manufacturer_Name, i.Inventory_Model,
i.Inventory_SerialNr, l.Event_ID, l.Inventory_ID
)
SELECT t.*
FROM t
WHERE seqnum = 1;
答案 1 :(得分:0)
WITH X AS (
SELECT ML.Log_StartDate As MaintDate
, M.M_Name
, I.Inventory_Model
, I.Inventory_SerialNr
, ML.Event_ID
, ML.Inventory_ID
, ROW_NUMBER() OVER (PARTITION BY ML.Inventory_ID
ORDER BY ML.Log_StartDate DESC)rn
FROM Maintenance_Log ML
INNER JOIN GL_Inventory I ON ML.Inventory_ID = I.Inventory_ID
INNER JOIN Manufacturer M ON I.M_ID = M.M_ID
WHERE ML.Owner_ID = @OwnerID
AND ML.Log_CompletedDate Is Null
)
SELECT MaintDate
,M_Name
,Inventory_Model
,Inventory_SerialNr
,Event_ID
,Inventory_ID
FROM X
WHERE RN = 1
答案 2 :(得分:0)
通常在这种情况下(需要从每个要连接的行的子查询得到前1个结果),CROSS APPLY就是你想要的。
INNER JOIN(选择前1 ...)对于要连接的每一行将使用相同的“前1”行,而CROSS APPLY(选择前1 ...)将评估要连接的每一行的表达式。
如果你需要它表现为LEFT OUTER JOIN(不过滤表达式中没有结果的行),请改用OUTER APPLY。
答案 3 :(得分:0)
由于每行的唯一性,查询完成了您的要求。
根据您发布的数据(假设第一个日期将具有最小的Maintenance_Log.Event_ID),下面的查询可能是一个解决方案。
SELECT MIN(Maintenance_Log.Log_StartDate) As MaintDate
, Manufacturer.Manufacturer_Name
, GL_Inventory.Inventory_Model
, GL_Inventory.Inventory_SerialNr
, MIN(Maintenance_Log.Event_ID)
, Maintenance_Log.Inventory_ID
FROM Maintenance_Log
INNER JOIN GL_Inventory ON Maintenance_Log.Inventory_ID = GL_Inventory.Inventory_ID
INNER JOIN Manufacturer ON GL_Inventory.Manufacturer_ID = Manufacturer.Manufacturer_ID
WHERE Maintenance_Log.Owner_ID = @OwnerID
AND Maintenance_Log.Log_CompletedDate Is Null
GROUP BY Maintenance_Log.Inventory_ID
, Maintenance_Log.Log_StartDate
, Manufacturer.Manufacturer_Name
, GL_Inventory.Inventory_Model
, GL_Inventory.Inventory_SerialNr
--, Maintenance_Log.Event_ID