5SK5 5SK5 - 5 months ago 7
SQL Question

Aggregate columns based off the same data

I have the following query -

SELECT d.PRD_YY,
Count(*)
FROM (SELECT CARD,
Min(TXN_DT) mindt
FROM db1.dbo.tblcards
GROUP BY CARD) a
JOIN db1.dbo.tlkpdates d
ON a.MINDT = d.GREG_DT
WHERE d.PRD_YY = 2016
AND d.PRD_NBR = 5
GROUP BY d.PRD_YY


basically, this tells me how many cards from my
tblcards
table first appeared in a given date range that is taken from the
tlkpdates
table by joining on
mindt
from my inner query result.

what I want to do is also see how many cards showed up in that date range altogether, and not just cards whose first occurrence was in that date range.

it doesn't seem like this is possible because i'm joining
greg_dt
(which is just a normal Gregorian date like 6/1/2016) on the minimum date, so how could i possible join on the maximum date (most recent occurrence)?

i know i can just make another query return that same data set but i'd rather have it in the same query.

edit - what also has to be considered is that i'm going to want to group on more than just PRD_YY - there's also a period number, period week, and period day, for a more granular view.

sample data -

Card Date Store Transaction
10123131444 2014-05-08 25 141414
40999999999 2013-12-07 847 15154
30999999998 2015-02-05 96 234235
20999999997 2016-03-21 139 2342525
50999999996 2016-03-30 659 1234121515
70999999995 2016-03-04 659 52525
50999999994 2016-03-03 907 2362362
20999999993 2014-05-23 941 2623626
70999999992 2013-12-03 18 123124
40999999991 2014-01-18 107 1512515


current output

prd_yy new_cards
2016 22911


desired output

prd_yy new_cards total_cards
2016 22911 54992

Answer

Assuming that card is a PK in the tblCards table (or at least only appears once each day at most), I think this will work for what you're trying to do:

SELECT
    D.prd_yy,
    SUM(CASE WHEN MD.card IS NOT NULL THEN 1 ELSE 0 END) AS new_cards,
    COUNT(*) AS total_cards
FROM
    dbo.tlkpDates D
INNER JOIN dbo.tblCards C ON C.txn_dt = D.greg_dt
LEFT OUTER JOIN (SELECT card, MIN(txn_dt) AS min_dt FROM dbo.tblCards GROUP BY card) MD ON
    MD.card = C.card AND MD.min_dt = C.txn_dt
WHERE
    D.prd_yy = '2016' AND
    D.prd_nbr = 5
GROUP BY
    D.prd_yy

Use the LEFT OUTER JOIN on the minimum dates as a flag for whether or not that particular day is the "first". Then you can use that with SUM(CASE...) to get your conditional count.

Comments