问题
I read through some of the answers but couldn't find the right answer for the following question. I have the below query that runs:
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
and I get the following result(sample):
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
So my MAX function doesn't work(probably because there are other columns with different value,just like in inv_trx_date) , what would be the best alternative to use? I would like to basically take the whole query and select MAX(inv_trx_date) as 'Latest Transaction' per each unique cst_recno as 'ID'.
回答1:
I think the canonical answer to this question is as follows
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)
In your case cst_recno
is the PK and inv_trx_date
is the MaxThing
回答2:
MAX works over the entire group you have specified. If you want the MAX aggregation to work for each unique cst_recno
then you need to group by only each unique cst_recno
.
回答3:
The issue of duplicate rows is because your CODE
and ivd_amount_cp
columns contain non-unique values in the recordset. Had they all contained the exact same information, your MAX
function would have worked without any problems.
You will have to use a Common Table Expression, as others have suggested. Let's assume you have a table that contains a specific CustomerID, and order dates, as well as a lot of other information. A customer can place multiple orders on the same date, and for whatever reason, we're only interested in the latest order of that customer. However, we do want to see all information related to that order.
The first thing we do is build a CTE to identify which order is the latest:
/* 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
)
Once you identified the MAX
of whatever you need, you then simply use that to identify all the other data you want to retrieve, by using the CTE to join back to the original table using the values you just obtained in the CTE:
SELECT
o.*
FROM
MyOrders o
JOIN myMaxOrder o1 ON o.CustomerID = o1.CustomerID
AND o1.MaxOrderID = o.OrderID
来源:https://stackoverflow.com/questions/46671164/max-date-wont-work-alternative