【问题标题】:Max date won't work, alternative?最大日期不起作用,替代方案?
【发布时间】:2017-10-10 16:04:32
【问题描述】:

我阅读了一些答案,但找不到以下问题的正确答案。我有以下运行的查询:

SELECT 
    mbr_src_code as 'C',
    cst_recno as 'ID',
    ind_first_name as 'FN',
    ind_last_name as 'LN',
    cst_org_name_dn as 'Company',
    cst_ixo_title_dn as 'Title',
    MAX(inv_trx_date) as 'Latest Transaction',
    inv_add_user as 'User',
    pyd_type as 'Type',
    bat_code as 'Code',
    mbr_add_user 'Add User',
    mbr_rejoin_date as 'rejoin',
    mbt_code,
    adr_state as 'state',
    adr_country as 'country',
    ivd_amount_cp
FROM 
    mb_membership  
JOIN 
    co_customer ON cst_key = mbr_cst_key AND mbr_delete_flag = 0  
LEFT JOIN 
    mb_member_type ON mbr_mbt_key = mbt_key 
LEFT JOIN 
    co_customer_x_address ON cxa_key = cst_cxa_key 
LEFT JOIN 
    co_address ON cxa_adr_key = adr_key 
LEFT JOIN 
    co_individual ON ind_cst_key = cst_key 
LEFT JOIN 
    mb_membership_x_ac_invoice ON mxi_mbr_key = mbr_key 
LEFT JOIN  
    ac_invoice ON mxi_inv_key = inv_key 
LEFT JOIN 
    ac_invoice_detail ON ivd_inv_key = inv_key 
LEFT JOIN 
    ac_payment_detail ON pyd_ivd_key = ivd_key 
LEFT JOIN 
    ac_payment ON pyd_pay_key = pay_key 
LEFT JOIN 
    ac_batch ON pay_bat_key = bat_key 
LEFT JOIN 
    ac_payment_info ON pay_pin_key = pin_key
LEFT JOIN 
    co_customer_x_customer ON cxc_cst_key_1 = co_customer.cst_key 
                           AND (cxc_end_date IS NULL OR DATEDIFF(dd, GETDATE(), cxc_end_date) >= 0) 
                           AND cxc_rlt_code = 'Chapter Member' 
LEFT JOIN 
    co_chapter ON cxc_cst_key_2 = chp_cst_key  
WHERE 
    (mbr_src_code LIKE N'%1DMFY18%' OR mbr_src_code LIKE N'%2DMFY18%' 
     OR mbr_src_code LIKE N'%INPhoneFY18%' OR mbr_src_code LIKE N'%OBTMFY18%' 
     OR mbr_src_code LIKE N'%3DMFY18%') 
    AND cst_recno = '20239'
GROUP BY  
    mbr_key, mbr_src_code, cst_recno, 
    ind_first_name, ind_last_name, cst_org_name_dn, cst_ixo_title_dn,
    inv_add_user, pyd_type, bat_code, mbr_add_user, mbr_rejoin_date,
    mbt_code, adr_state, adr_country, pin_cc_number_display, pin_cc_cardholder_name,
    ivd_amount_cp, chp_name
ORDER BY
    ind_last_name

我得到以下结果(示例):

      C       ID    FN    LN       Company          Title       Latest transaction     User              Type          Code                    Add User    rejoin   mbt_code           state  country    ivd_amount_cp     
    2DMFY18 20239   Gus Bauman  Beveridge & Diamond Attorney    2013-09-23 00:00:00 Membership Renewal  Payment 2013-09-23-ULI-USD-C-SP-01  ULI_Conversion  NULL    Associate Member    DC  UNITED STATES   430.00  
    2DMFY18 20239   Gus Bauman  Beveridge & Diamond Attorney    2014-08-04 00:00:00 Membership Renewal  Payment 2014-08-04-ULI-USD-C-SP-01  ULI_Conversion  NULL    Associate Member    DC  UNITED STATES   430.00  
    2DMFY18 20239   Gus Bauman  Beveridge & Diamond Attorney    2015-09-02 00:00:00 Membership Renewal  Payment 2015-09-02-ULI-USD-C-SP-02  ULI_Conversion  NULL    Associate Member    DC  UNITED STATES   440.00  
    2DMFY18 20239   Gus Bauman  Beveridge & Diamond Attorney    2016-09-12 00:00:00 Membership Renewal  Payment 2016-09-12-ULI-USD-C-SP-01  ULI_Conversion  NULL    Associate Member    DC  UNITED STATES   440.00  
    2DMFY18 20239   Gus Bauman  Beveridge & Diamond Attorney    2017-09-22 00:00:00 Membership Renewal  Payment 2017-09-22-ULI-USD-C-SP-01  ULI_Conversion  NULL    Associate Member    DC  UNITED STATES   440.00

所以我的 MAX 函数不起作用(可能是因为其他列具有不同的值,就像 inv_trx_date 一样),最好的选择是什么?我想基本上采用整个查询并选择 MAX(inv_trx_date) 作为 'Latest Transaction' 每个唯一的 cst_recno 作为 'ID'。

【问题讨论】:

  • 请编辑您问题中的代码,使其成为显示问题的绝对最小值(提示:您不需要任何连接,只需几列即可实现)。

标签: sql sql-server sql-server-2012 max temp


【解决方案1】:

我认为这个问题的规范答案如下

with AllData as
(
select ... from ...
where ...
)
select * from allData ad1
inner join 
(
    select pk1, pk2, pk<n>, max(MaxThing) MaxVal 
    from AllData
    group by pk1, pk2, pk<n>
) as ad2 
on (ad1.pk1=ad2.pk1 and ad1.pk2=ad2.pk2 and ad1.pk<n>=ad2.pk<n> 
and  ad1.MaxThing=ad2.MaxVal)

在您的情况下,cst_recno 是 PK,inv_trx_date 是 MaxThing

【讨论】:

    【解决方案2】:

    MAX 适用于您指定的整个组。如果您希望 MAX 聚合适用于每个唯一的 cst_recno,那么您只需要按每个唯一的 cst_recno 进行分组。

    【讨论】:

    • 它不起作用,如果我只按 cst_recno 分组。它需要按 select 语句中的所有列分组,但具有聚合函数的列(MAX(inv_trx_date) as 'Latest Transaction',)
    • Msg 8120,Level 16,State 1,Line 2 列 'mb_membership.mbr_src_code' 在选择列表中无效,因为它既不包含在聚合函数中,也不包含在 GROUP BY 子句中。
    • 您不能选择 mbr_src_code,因为它不是组独有的,您要么需要将该列添加到 group by 子句中,将其从 select 子句中删除,要么对其进行聚合选择子句。
    • 我需要在结果中包含所有这些列(上面的查询)。
    • 如何根据上面的结果创建一个临时表,然后选择 MAX(inv_trx_date) 作为“最新交易”?这可行吗?
    【解决方案3】:

    重复行的问题是因为您的CODEivd_amount_cp 列在记录集中包含非唯一值。如果它们都包含完全相同的信息,您的MAX 函数将毫无问题地工作。

    正如其他人所建议的那样,您将不得不使用公用表表达式。假设您有一个包含特定 CustomerID 和订单日期以及许多其他信息的表。客户可以在同一日期下多个订单,无论出于何种原因,我们只对该客户的最新订单感兴趣。但是,我们确实希望查看与该订单相关的所有信息。

    我们要做的第一件事是构建一个 CTE 来识别哪个订单是最新的:

    /* Example table */
    CREATE TABLE myOrders
    (
        OrderID int IDENTITY(1,1)
        , CustomerID int 
        , OrderDate datetime
        , ImportantInfo nvarchar(255)
    )
    ;
    
    /* Some test data to work with */
    INSERT INTO myOrders 
    VALUES (
        1, '01-01-2017', 'We do not want this row'
    ), (
        1, '01-02-2017', 'We do not want this row either'
    ),  (
        1, '01-10-2017', 'Getting closer, but not this one either'
    ),  (
        1, '01-10-2017', 'This is the one we want!'
    )
    ;
    
    WITH myMaxOrder AS 
    (
        SELECT CustomerID, MAX(OrderID) AS MaxOrderID
        FROM myORders
        GROUP BY CustomerID
    )
    

    一旦您确定了您需要的任何MAX,然后您只需使用它来识别您想要检索的所有其他数据,方法是使用 CTE 使用您刚刚在CTE:

    SELECT 
        o.* 
    FROM 
        MyOrders o
        JOIN myMaxOrder o1 ON o.CustomerID = o1.CustomerID 
        AND o1.MaxOrderID = o.OrderID
    

    【讨论】:

      猜你喜欢
      • 2018-04-26
      • 2018-10-15
      • 1970-01-01
      • 2012-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-13
      • 1970-01-01
      相关资源
      最近更新 更多