OM Asphyxiate
OM Asphyxiate

Reputation: 329

Show 0 for null rows

I'm working on a comparison query that will compare what was processed for the different credit card types versus what was actually processed by our POS service. I have ran into an issue where I am not seeing rows for certain card types if they did not process any payments on a given day but may have given a refund. IE: Nothing purchased with VISA but a VISA refund was given, but due to no purchases the row does not show up even though there's a refund for that type.

Here is my query:

WITH tran_total AS (
SELECT  CONCAT(c.id_str, ' - ', c.clinic_str) AS Clinics, 
        t.clinic, 
        c.xcharge_mid, 
        p.pay_desc, 
        CAST(t.time_ran AS date) AS tran_date, 
        CASE WHEN SUM(t.amount) <> 0 THEN SUM(t.amount) * - 1 
        ELSE 0.00 END AS collection
FROM dbo.transactions AS t INNER JOIN
dbo.clinic_master AS c ON t.clinic = c.clinic INNER JOIN
dbo.paytype AS p ON t.clinic = p.clinic AND t.paytype_id = p.paytype_id
WHERE (t.time_ran > GETDATE() - 10) 
AND (t.paytype_id IS NOT NULL) 
AND (p.pay_desc = 'Visa' OR
p.pay_desc = 'MasterCard' OR
p.pay_desc = 'American Express' OR
p.pay_desc = 'Discover')
GROUP BY c.id_str, c.clinic_str, t.clinic, c.xcharge_mid, p.pay_desc, CAST(t.time_ran AS date))
SELECT  w.Clinics, 
        w.pay_desc, 
        w.tran_date, 
        w.collection, 
        CASE WHEN w.pay_desc = 'Visa' THEN (SUM(VI_pur) - SUM(VI_ref)) 
        WHEN w.pay_desc = 'MasterCard' THEN (SUM(MC_pur) - SUM(MC_ref)) 
        WHEN w.pay_desc = 'American Express' THEN (SUM(AX_pur) - SUM(AX_ref)) 
        WHEN w.pay_desc = 'Discover' THEN (SUM(DI_pur) - SUM(DI_ref)) END AS xcharge
FROM            tran_total AS w LEFT OUTER JOIN
dbo.xcharge AS x ON w.xcharge_mid = x.xcharge_mid AND w.tran_date = x.settle_date
GROUP BY w.Clinics, w.pay_desc, w.tran_date, w.collection
ORDER BY w.Clinics, w.tran_date

I've thought about switching this around and starting with the comparison from the xcharge table but there is not a pay_desc that links those easily and if something is processed as the wrong card (VISA is chosen but Discover is scanned) then I feel the rows would be missed still.

What I would like, is for all of the pay_desc to show up for each tran_date even if the SUM(t.amount) does not have a value. I've tried a case statement to accomplish this without any luck.

EDIT: I feel the issue is more due to the t.time_ran variable. If there isn't a payment for a given pay_desc then there won't be a t.time_ran either, is there a function I can do to list out dates between GETDATE()-10 AND GETDATE() kind of thing and just have the t.time_ran and x.settle_date match up to that variable instead?

Any thoughts on this? Thanks in advance

UPDATE:

I have created a calendar table with individual dates and have tried the following query:

WITH tran_test AS(
SELECT  cal.calendardate AS cd, 
        p.clinic, 
        p.pay_desc,
        p.paytype_id
FROM calendar cal, paytype p
WHERE cal.calendardate BETWEEN GETDATE()-10 AND GETDATE()+1
AND (p.pay_desc = 'Visa' OR
p.pay_desc = 'MasterCard' OR
p.pay_desc = 'American Express' OR
p.pay_desc = 'Discover'))
SELECT  w.cd, 
        CONCAT(c.id_str, ' - ', c.clinic_str) AS Clinics, 
        w.pay_desc, 
        ISNULL(SUM(t.amount)*-1, 0) AS collection,
        CASE WHEN w.pay_desc = 'Visa' THEN (SUM(x.VI_pur) - SUM(x.VI_ref)) 
        WHEN w.pay_desc = 'MasterCard' THEN (SUM(x.MC_pur) - SUM(x.MC_ref)) 
        WHEN w.pay_desc = 'American Express' THEN (SUM(x.AX_pur) - SUM(x.AX_ref)) 
        WHEN w.pay_desc = 'Discover' THEN (SUM(x.DI_pur) - SUM(x.DI_ref)) END AS xcharge
FROM tran_test w
INNER JOIN clinic_master c
    ON (w.clinic=c.clinic)
LEFT OUTER JOIN transactions t
    ON (t.clinic=w.clinic AND t.paytype_id=w.paytype_id AND CAST(t.time_ran AS date) = w.cd)
LEFT OUTER JOIN xcharge x
    ON (w.cd=x.settle_date AND c.xcharge_mid=x.xcharge_mid)
GROUP BY w.cd, c.id_str, c.clinic_str, w.pay_desc
ORDER BY w.cd

However, I'm not getting an issue where my xcharge column seems to multiplying itself by random intervals and I'm not sure why.

Upvotes: 0

Views: 209

Answers (1)

Tom H
Tom H

Reputation: 47444

It sounds like what you need is a Calendar table. You can generate one as part of a CTE (many examples on this site or just search Google), but IMO you should have a persistent table in your database. This way you can mark certain days as bank holidays, what quarter your business considers them to be in, etc.

Once you have that table in place you can SELECT your dates from that table and then LEFT OUTER JOIN to that table from your Transactions table. Any dates without matching rows in Transactions will still show up with a row, but you'll have 0.00 value for your SUM.

Upvotes: 1

Related Questions