SQL Server分组查询基于一对多关系

时间:2018-07-31 14:48:33

标签: sql sql-server sql-server-2012

我有2个具有一对多关系的SQL SERVER表

Table : Orders
---------------
BILL_NO    QUANTITY
100         1
101         2

Table : Mobility
----------------
MOBILITY_UID      BILL_NO           DATE        CURRENT_LOCATION
1                 101               20/07/18    1_NO-SHOP 
2                 101               21/07/18    2_NO_SHOP
3                 102               21/07/18    WORKSHOP

现在我需要一个查询来根据BILL的上次位置更新获取哪个位置有多少订单(例如2_NO_SHOP是BILL no 101的最后一个位置,因为它最后一次使用MOBILITY_UID = 2进行了更新)

预期结果:

CURRENT_LOCATION   QUANTITY
1_NO_SHOP          0
2_NO_SHOP          2
WORKSHOP           1

3 个答案:

答案 0 :(得分:1)

outer apply按位置获取数量-但不获取零数量。

select m.current_location, o.quantity
from orders o outer apply
     (select top (1) m.*
      from mobility m
      where m.bill_no = o.bill_no
      order by date desc
     ) m;

我将建议:

select l.location, coalesce(mo.quantity, 0) as quantity
from (select distinct current_location as location from mobility) l left join
     (select m.current_location, o.quantity
      from orders o outer apply
           (select top (1) m.*
            from mobility m
            where m.bill_no = o.bill_no
            order by date desc
           ) m
     ) mo
     on mo.current_location = l.location

另一种方法使用row_number()

select m.current_location,
       max(case when seqnum = 1 then o.quantity else 0 end) as quantity
from (select m.*, row_number() over (partition by m.bill_no order by m.date desc) as seqnum
      from mobility m
      order by date desc
     ) m left join
     orders o
     on m.bill_no = o.bill_no

答案 1 :(得分:0)

也许这可以解决问题?

SELECT 
    CURRENT_LOCATION
,   quantity 
FROM (
SELECT 
    M.CURRENT_LOCATION
,   CASE WHEN Bill_DATE = MAX(M.Bill_DATE) OVER(PARTITION BY M.BILL_NO ORDER BY M.Bill_DATE DESC) THEN O.quantity ELSE 0 END  quantity
,   ROW_NUMBER() OVER(PARTITION BY M.BILL_NO ORDER BY M.Bill_DATE DESC) RN
FROM Mobility M
LEFT JOIN Orders O ON O.BILL_NO = M.BILL_NO
) D 
ORDER BY CURRENT_LOCATION

答案 2 :(得分:0)

我做了一个函数

IF OBJECT_ID (N'dbo.getCurrentLocation', N'FN') IS NOT NULL  
    DROP FUNCTION getCurrentLocation;  
GO  
CREATE FUNCTION dbo.getCurrentLocation(@BILLNO VARCHAR(10))  
RETURNS VARCHAR(20)   
AS   
BEGIN  
    DECLARE @ret VARCHAR(20);  
    SELECT @ret = (SELECT TOP 1 CURRENT_LOCATION  
    FROM MOBILITY OM   
    WHERE OM.BILL_NO = @BILLNO  
          ORDER BY MOBILITY_UID DESC)
     IF (@ret IS NULL)   
        SET @ret = '';  
    RETURN @ret;  
END;

然后使用汇总查询

SELECT DBO.getCurrentLocation(od.BILL_NO) AS LOCATION 
,sum(OD.QUANTITY) FROM ORDERS OD 
where DBO.getCurrentLocation(od.BILL_NO) <> '' 
group by  DBO.getCurrentLocation(od.BILL_NO)