CTE with paging returning random value from subquery - sql

I have a table with contact(contacts) information and another relationship table with key/value data for the contact table (customdata), the custom data rows are not unique, they can repeat, and they have a creation date as well.
I have a CTE querying the contacts, pretty simple, but I also want to return subquery column with from particular key, and the value from this query happens to contain a date, stored as varchar, and since this table does not contain unique rows I'm using TOP 1 and sorting by the row creation date.
The issue I'm having is that the value from the custom data table is returning random values and to top it off its not sorting correctly when casted to date.
WITH Customers_CTE AS(
SELECT row_number() over (ORDER BY (SELECT TOP 1 CONVERT(DATETIME, data_value, 101)
FROM CustomData
WHERE (data_cust_id = Customers.cust_id AND data_key = 'Sign Date' AND ISDATE(data_value) = 1) ORDER BY data_created DESC) DESC) AS rowNum,
COUNT(*) OVER (PARTITION BY NULL) AS [RowCount],
Customers.FirstName,
Customers.LastName,
(SELECT TOP 1 CONVERT(DATETIME, data_value, 101)
FROM CustomData
WHERE (data_cust_id = Customers.cust_id AND data_key = 'Sign Date' AND ISDATE(data_value) = 1) ORDER BY data_created DESC) AS DateSigned
FROM Customers)
SELECT * FROM Customers_CTE
WHERE rowNum >= 0 and rowNum < 10
Data sample
CUSTOMERS
cust_id, cust_firstname, cust_lastname
--------------------------------------
1 , john , doe
2 , jane , mary
CUSTOM DATA
data_created, data_cust_id, data_key , data_value
------------------------------------------------------
2018-04-06 , 1 , 'Sign Date' , '2018-03-17'
2018-04-06 , 1 , 'Agreed' , 'Yes'
2019-03-12 , 1 , 'Renew Date' , '2019-01-25'
2020-04-11 , 2 , 'Sign Date' , '2020-03-28'
2020-04-11 , 2 , 'Agreed' , 'Yes'
2020-06-07 , 1 , 'Sign Date' , '2020-05-13'
2020-10-21 , 2 , 'Sign Date' , '2020-09-15'
RESULT
FirstName , LastName , DateSigned
-------------------------------------
jane , mary , 2020-09-15
john , doe , 2020-05-13

I'm struggling to see what's going on with your CTE or what you are trying to do, it's just wriddled with syntax errors or issues.
If this helps, to get your desired output from your sample data, you just need the following - if I've understood your sample data you just want the maximum date value for each customer Id for a particular "key" value:
select c.cust_firstname, c.cust_lastname, d.DateSigned
from customers c
outer apply (
select Max(Try_Convert(date,data_value)) DateSigned
from customdata cd
where cd.data_cust_id=c.cust_id and cd.data_key='Sign date'
)d

Related

Total customer per reporting date without union

I would like to display to run this report where I show the total number of customers per reporting date. Here is a how I need the data to look like:
My original dataset look like this (please see query): In order to calculate the number of customers. I need to use the start and end date: if Start_Date>reporting_date and End_Date<=reporting_date then count as a customer.
I was able to develop a script, but it only gives me the total number of customers for only one reporting date.
select '2022-10-31' reporting_date, count(case when Start_Date>'2022-10-31' and End_Date<='2022-10-31' then Customer_ID end)
from (values ('2022-10-14','2022-8-19','0010Y654012P6KuQAK')
, ('2022-3-15','2022-9-14','0011v65402PoSpVAAV')
, ('2021-1-11','2022-10-11','0010Y654012P6DuQAK')
, ('2022-12-1','2022-5-14','0011v65402u7muLAAQ')
, ('2021-1-30','2022-3-14','0010Y654012P6DuQAK')
, ('2022-10-31','2022-2-14','0010Y654012P6PJQA0')
, ('2021-10-31','US','0010Y654012P6PJQA0')
, ('2021-5-31','2022-5-14','0011v65402x8cjqAAA')
, ('2022-6-2','2022-1-13','0010Y654016OqkJQAS')
, ('2022-1-1','2022-11-11','0010Y654016OqIaQAK')
) a(Start_Date ,End_Date ,Customer_ID)
Is there a way to amend the code with cross-join or other workarounds to the total customers per reporting date without doing many unions
select '2022-10-31' reporting_date, count(case when Start_Date>'2022-10-31' and End_Date<='2022-10-31' then Customer_ID end)
from (values ('2022-10-14','2022-8-19','0010Y654012P6KuQAK')
, ('2022-3-15','2022-9-14','0011v65402PoSpVAAV')
, ('2021-1-11','2022-10-11','0010Y654012P6DuQAK')
, ('2022-12-1','2022-5-14','0011v65402u7muLAAQ')
, ('2021-1-30','2022-3-14','0010Y654012P6DuQAK')
, ('2022-10-31','2022-2-14','0010Y654012P6PJQA0')
, ('2021-10-31','US','0010Y654012P6PJQA0')
, ('2021-5-31','2022-5-14','0011v65402x8cjqAAA')
, ('2022-6-2','2022-1-13','0010Y654016OqkJQAS')
, ('2022-1-1','2022-11-11','0010Y654016OqIaQAK')
) a(Start_Date ,End_Date ,Customer_ID)
UNION ALL
select '2022-9-30' reporting_date, count(case when Start_Date>'2022-9-301' and End_Date<='2022-9-30' then Customer_ID end)
from (values ('2022-10-14','2022-8-19','0010Y654012P6KuQAK')
, ('2022-3-15','2022-9-14','0011v65402PoSpVAAV')
, ('2021-1-11','2022-10-11','0010Y654012P6DuQAK')
, ('2022-12-1','2022-5-14','0011v65402u7muLAAQ')
, ('2021-1-30','2022-3-14','0010Y654012P6DuQAK')
, ('2022-10-31','2022-2-14','0010Y654012P6PJQA0')
, ('2021-10-31','US','0010Y654012P6PJQA0')
, ('2021-5-31','2022-5-14','0011v65402x8cjqAAA')
, ('2022-6-2','2022-1-13','0010Y654016OqkJQAS')
, ('2022-1-1','2022-11-11','0010Y654016OqIaQAK')
) a(Start_Date ,End_Date ,Customer_ID)
It is possible to provide date ranges as a separate table/subquery, join to the actual data and perform grouping:
select s.start_d, s.end_d, COUNT(Customer_ID) AS total
FROM (SELECT '2022-10-31'::DATE, '2022-10-31'::DATE
UNION SELECT '2022-09-30', '2022-09-30')
AS s(start_d, end_d)
LEFT JOIN (values ('2022-10-14','2022-8-19','0010Y654012P6KuQAK')
, ('2022-3-15','2022-9-14','0011v65402PoSpVAAV')
, ('2021-1-11','2022-10-11','0010Y654012P6DuQAK')
, ('2022-12-1','2022-5-14','0011v65402u7muLAAQ')
, ('2021-1-30','2022-3-14','0010Y654012P6DuQAK')
, ('2022-10-31','2022-2-14','0010Y654012P6PJQA0')
, ('2021-10-31','2021-10-31','0010Y654012P6PJQA0')
, ('2021-5-31','2022-5-14','0011v65402x8cjqAAA')
, ('2022-6-2','2022-1-13','0010Y654016OqkJQAS')
, ('2022-1-1','2022-11-11','0010Y654016OqIaQAK')
) a(Start_Date ,End_Date ,Customer_ID)
ON a.Start_Date>s.start_d and a.End_Date<=s.end_d
GROUP BY s.start_d, s.end_d;
Output:

SQL - Returning the Top two Results for Each Match

I have a situation where we record every change to a column of a member record in the MEMBER table as a separate row. The changes that are logged only show the column name that was changed, the new value and the date the change was made.
Example: Table Name - CustomerChanges
customerId
columnName
newValue
dateChanged
1234
status
Active
1/12/2021
1234
status
Cancelled
9/30/2020
1234
status
Frozen
7/1/2020
1234
status
Active
1/1/2020
5678
status
Active
1/11/2021
5678
status
Frozen
11/1/2020
5678
status
Active
2/1/2020
9101
status
Active
1/10/2021
9101
type
Full Time
1/10/2021
9101
status
Frozen
10/15/2020
9101
status
Active
1/1/2020
I need to do 3 things here:
Pull all of the changes for status only
Grab all of the Customers that went from Frozen to Active. I believe the way to go about it is to pull the top two records for each customerId and then see who went from Frozen to Active.
Who did it in the specified time frame...in this example it would be January.
Considerations:
As stated earlier, the table has changes for all columns just not the status column.
The Customer can have many entries of status changes.
I am working in SSRS and have been struggling with this. I tried to query the table for changes to the column columnName, group it by CustomerId, grab the top two rows and then see which ones went from Frozen to Active.
Thank you in advance.
This is a bit messy, there is probably a better way of doing it but this should work.
You will have to adjust the inner-most query to filter on your date range, I didn't include that bit.
I recreated your dataset and then produced the output as follows
DECLARE #t TABLE (customerId int, columnName varchar(20), newValue varchar(20), dateChanged date)
INSERT INTO #t VALUES
(1234, 'status', 'Active' , '2021-01-12' ),
(1234, 'status', 'Cancelled', '2020-09-30' ),
(1234, 'status', 'Frozen' , '2020-07-01' ),
(1234, 'status', 'Active' , '2020-01-01' ),
(5678, 'status', 'Active' , '2021-01-11' ),
(5678, 'status', 'Frozen' , '2020-11-01' ),
(5678, 'status', 'Active' , '2020-02-01' ),
(9101, 'status', 'Active' , '2021-01-10' ),
(9101, 'type', 'Full Time' , '2021-01-10' ),
(9101, 'status', 'Frozen' , '2020-10-15' ),
(9101, 'status', 'Active' , '2020-01-01' )
--SELECT * FROM #t
SELECT * FROM
(
SELECT
s.*
, LAG(newValue, 1) OVER(PARTITION BY customerId ORDER BY dateChanged) AS PreviousStatus
FROM
(SELECT *, ROW_NUMBER() OVER(PARTITION BY CustomerID ORDER BY dateChanged DESC) as RowN
FROM #t
WHERE columnName = 'Status' -- Add date filtering here
) s
WHERE s.RowN < =2
) x
WHERE newValue = 'Active' AND PreviousStatus = 'Frozen'
This gives the following output

How can I find the difference of two sums based on the Dates and the Same PK Individualid number

I need to find duplicate individualIDs and determine which IndividualIDs have improved.
For example, for each IndividualID I need the sum of C_Q1, C_Q2, C_Q3, C_Q4, C_Q5 and based on the date and 1 being the most improvement and 5 being the least improvement, count that IndividualID if the 2nd sum is a lower number than the first number and would determine which is the 1st number by the UpdateDate being the earliest date and the 2nd number is for the later date.
For Anxiety_Arr, Hyper_Arr, Exagg_Arr, Anxiety_Dep, Hyper_Dep, Exagg_Dep, 1 is the least improvement and 0 is the most improvement, so after summing those it would be counted if the second sum is less than the first sum.
This is the code to get the sums I need but then need help to find out how to compare the 1st and 2nd numbers for each individualID and the count of individuals who have the 2nd sum being lower than the 1st sum.
select distinct
IND.Individuals_IndividualID
, C.ATQChild_IndividualID
, ANS.ANS_IndividualID
, C.UpdateDate as ATQChild_UpdateDate
, ANS.UpdateDate as ANS_UpdateDate
, c.q1_c as C_Q1
, c.q2_c as C_Q2
, c.q3_c as C_Q3
, c.q4_c as C_Q4
, c.q5_c as C_Q5
, Sum(isnull(cast(Q1_c as int),0)) + Sum(isnull(cast(Q2_c as int),0)) + Sum(isnull(cast(Q3_c as int),0)) + Sum(isnull(cast(Q4_c as int),0)) + Sum(isnull(cast(Q5_c as int),0)) as ChildSum
, Sum(isnull(cast(anxiety_arr as int),0)) + Sum(isnull(cast(hyper_arr as int),0)) + Sum(isnull(cast(exagg_arr as int),0)) as ANS_ArrSum
, Sum(isnull(cast(anxiety_dep as int),0)) + Sum(isnull(cast(hyper_dep as int),0)) + Sum(isnull(cast(exagg_dep as int),0)) as ANS_DepSum
, CASE WHEN (ANS.[anxiety_arr])='TRUE' THEN 1 ELSE 0 END as Anxiety_Arr
, CASE WHEN (ANS.[hyper_arr])='TRUE' THEN 1 ELSE 0 END as Hyper_Arr
, CASE WHEN (ANS.[exagg_arr])='TRUE' THEN 1 ELSE 0 END as Exagg_Arr
, CASE WHEN (ANS.[anxiety_dep])='TRUE' THEN 1 ELSE 0 END as Anxiety_Dep
, CASE WHEN (ANS.[hyper_dep])='TRUE' THEN 1 ELSE 0 END as Hyper_Dep
, CASE WHEN (ANS.[exagg_dep])='TRUE' THEN 1 ELSE 0 END as Exagg_Dep
from DBO.tb_cdcp_individuals ind
left join DBO.tb_cdcp_ATQChild c on c.[tb_cdcp_individuals] = ind.[tb_cdcp_individuals]
left join DBO.tb_cdcp_ans_checklist ANS on ans.[tb_cdcp_individuals] = ind.[tb_cdcp_individuals]
group by IND.tb_cdcp_individuals,C.[tb_cdcp_individuals],ANS.[tb_cdcp_individuals],C.UpdateDate,ANS.UpdateDate
, c.q1_c
, c.q2_c
, c.q3_c
, c.q4_c
, c.q5_c
, ANS.Anxiety_Arr
, ANS.hyper_arr
, ANS.exagg_arr
, ANS.Anxiety_Dep
, ANS.Hyper_Dep
, ANS.Exagg_Dep
You can use the lag/lead functions to compare consecutive records for an ID. For example, for the following sample (Assuming that the table name is temp):
ID Date CQ1To5
1 1/1/2019 10
1 1/2/2019 5
select *,lag(CQ1To5,1) Over(Partition by ID Order by Date) as lag_date,
Case when lag(CQ1To5,1) Over(Partition by ID Order by Date) is NULL then 0
when lag(CQ1To5,1) Over(Partition by ID Order by Date)<CQ1To5 then 1 else 0 end as Flag from temp
This should give you the following output:
ID Date CQ1To5 Lag_date Flag
1 1/1/2019 10 5 1
1 1/2/2019 5 NULL 0
Your flag value should be 1 wherever the next record of the ID is an improvement. You can modify this query to fit your specific needs. Hope this helps.
Note: CQ1to5 indicates the sum of all the 5 fields you mentioned
You can do the same using joins and row number:
select *,Row_number() Over(Partition by ID Order by Date) as rownum
into #temp1
from #temp
select a.*,b.CQ1to5,case when a.CQ1to5<b.CQ1to5 then 1 else 0 end as flag
into #temp2
from #temp1 a left join #temp1 b on a.id=b.id and a.rownum=b.rownum+1
select *,row_number() over(Partition by ID,flag order by Date) as rownum1
into #temp3
from #temp2
UPDATE #temp3
SET flag=0
where flag=1 and rownum1>1

How to display data on separate rows in one row

I have a table with the following setup
ID InOut_Status InOut_Datetime
1 IN 9/12/2017 8:00
2 IN 9/12/2017 10:00
1 OUT 9/12/2017 1:00
2 OUT 9/12/2017 3:00
I want to be able to see both status and date on the same row vs separate rows for example
ID In_Status In_Datetime Out_Status Out_Datetime
1 IN 9/12/2017 8:00 OUT 9/12/2017 1:00
2 IN 9/12/2017 10:00 OUT 9/12/2017 3:00
I would like to return all columns. I just provided a few for example. I also would like to show only the most recent Datetime for each ID and if the user hasn't checked out, I would like for the Out_Datetime to be blank.
Any assistance would be greatly appreciated. Thanks.
You can use self join:
SELECT *
FROM
(
SELECT ins.id
, ins.InOut_Datetime as in_time
, outs.InOut_Datetime as out_time
, row_number() over (partition by ins.id order by ins.InOut_Datetime desc) as ranking
FROM table ins
LEFT JOIN table outs
ON ins.id = outs.id
AND outs.InOut_Status = 'OUT'
AND outs.InOut_Datetime > ins.InOut_Datetime
WHERE ins.InOut_Status = 'IN'
and ins.InOut_Datetime > DATEADD(day, -1, GETDATE())
) t
WHERE t.ranking = 1
Updated query to :
get logins within last 24 hours
get the latest login of a user only
show out time only if it's later than in time
You need to left join, however, you want to limit the join to the first record returned in descending order using a sub query.
SELECT * FROM
(
SELECT
ID,InOut_Status,InOutDateTime,
CheckOutInstanceDescending = ROW_NUMBER() OVER(PARTITION BY ClockOut.ID ORDER BY ClockOut.InOutDateTime DESC)
FROM
MyTable ClockIn
LEFT OUTER JOIN MyTable ClockOut ON ClockOut.ID=ClockIn.ID
WHERE
ClockIn.InOut_Status='IN'
)AS Combined
WHERE
Combined.CheckOutInstanceDescending=1
A simple pivot would fix this the easiest:
https://technet.microsoft.com/en-us/library/ms177410(v=sql.105).aspx. You can run this in SSMS 2008 or higher(I wrote it in SQL 2016).
DECLARE #Temp TABLE (Id INT, InOut_Status VARCHAR(8), InOut_Datetime DATETIME)
INSERT INTO #Temp (Id, InOut_Status, InOut_Datetime) VALUES (1, 'IN', '9-12-2017 8:00'), (2, 'IN', '9-12-2017 10:00'),(1, 'OUT', '9-12-2017 13:00'),(2, 'OUT', '9-12-2017 16:00'),(3, 'IN', '9-12-2017 06:00')
SELECT
pvt.Id
, 'IN' AS In_Status
, pvt.[In]
, 'OUT' AS Out_Status
, pvt.OUT
From #Temp
PIVOT(MAX(InOut_Datetime) FOR InOut_Status IN ([In], [OUT])) AS pvt

Oracle SQL- Flag records based on record's date vs history

This is my 1st post on the forum. Usually I was able to find what I needed - but to tell the truth - I am not really sure how to ask a correct question to the issue. Therefore, please accept my apologies if there already is an answer on the forum and I missed it.
I am running the following code in an Oracle database via Benthic Software:
SELECT
T1."REGION"
, T1."COUNTRY"
, T1."IDNum"
, T1."CUSTOMER"
, T1."BUSSINESS"
, T3."FISCALYEARMONTH"
, T3."FISCALYEAR"
, SUM(T4."VALUE")
,"HISTORICAL_PURCHASE_FLAG"
FROM
"DATABASE"."SALES" T4
, "DATABASE"."CUSTOMER" T1
, "DATABASE"."PRODUCT" T2
, "DATABASE"."TIME" T3
WHERE
T4."CUSTOMERID" = T1."CUSTOMERID"
AND T4."PRODUCTID" = T2."PRODUCTID"
AND T4."DATEID" = T3."DATEID"
AND T3."FISCALYEAR" IN ('2016')
AND T1."COUNTRY" IN ('ENGLAND', 'France')
GROUP BY
T1."REGION"
, T1."COUNTRY"
, T1."IDNum"
, T1."CUSTOMER"
, T1."BUSSINESS"
, T3."FISCALYEARMONTH"
, T3."FISCALYEAR"
;
This query provides me with information on transactions. As you can see above, I would like to add a column named "HISTORICAL_PURCHASE_FLAG".
I would like the query to take CUSTOMER and FISCALYEARMONTH. Then, I would like to check if there are any transactions registered for the CUSTOMER, up to 2 years in the past.
So lets say I get the following result:
LineNum REGION COUNTRY IDNum CUSTOMER BUSSINESS FISCALYEARMONTH FISCALYEAR VALUE HISTORICAL_PURCHASE_FLAG
1 Europe ENGLAND 255 Abraxo Cleaner Co. Chemicals 201605 2016 34,567.00
2 Europe FRANCE 123 Metal Trade Heavy 201602 2016 12,500.00
3 Europe ENGLAND 255 Abraxo Cleaner Co. Chemicals 201601 2016 8,400.00
LineNum 1 shows transaction for Abraxo Cleaner Co. registered on 201605. And LineNum 3 is also for Abraxo Cleaner Co. but registered on 201601. What I would need the query to do, is to flag LineNum 1 as 'Existing'. Because there was a previous transaction registered.
On the other hand, LineNum 3 was the first time transactions was registered for Abraxo Cleaner Co. so the line would be flagged as 'New'.
To sum up, I would like for each row of data to be treated individually. And to check if there are any previous records of data for CUSTOMER & FISCALYEARMONTH - 24 months.
Thank you in advance for the help.
You can use LAG function:
SELECT
"REGION"
, "COUNTRY"
, "IDNum"
, "CUSTOMER"
, "BUSSINESS"
, "FISCALYEARMONTH"
, "FISCALYEAR"
, SUM("VALUE")
, MAX(CASE WHEN to_date(prev_fym,'YYYYMM') >= ADD_MONTHS (to_date("FISCALYEARMONTH",'YYYYMM'), -24) THEN 'Existing'
ELSE NULL END) "HISTORICAL_PURCHASE_FLAG"
FROM
(
SELECT
T1."REGION"
, T1."COUNTRY"
, T1."IDNum"
, T1."CUSTOMER"
, T1."BUSSINESS"
, T3."FISCALYEARMONTH"
, T3."FISCALYEAR"
, T4."VALUE"
, LAG ("FISCALYEARMONTH", 1) OVER (PARTITION BY T1."IDNum" ORDER BY T3."FISCALYEARMONTH" DESC) prev_fym
FROM
"DATABASE"."SALES" T4
, "DATABASE"."CUSTOMER" T1
, "DATABASE"."PRODUCT" T2
, "DATABASE"."TIME" T3
WHERE
T4."CUSTOMERID" = T1."CUSTOMERID"
AND T4."PRODUCTID" = T2."PRODUCTID"
AND T4."DATEID" = T3."DATEID"
AND T1."COUNTRY" IN ('ENGLAND', 'France')
AND T3."FISCALYEAR" IN ('2014','2015','2016')
)
WHERE "FISCALYEAR" IN ('2016')
GROUP BY
"REGION"
, "COUNTRY"
, "IDNum"
, "CUSTOMER"
, "BUSSINESS"
, "FISCALYEARMONTH"
, "FISCALYEAR"
;
Using a simplified "input" table... You can use the LAG() analytic function and a comparison condition to populate your last column. I assume your fiscalyearmonth is a number - if it is a character field, wrap fiscalyearmonth within TO_NUMBER(). (It would be much better if in fact you stored these as true Oracle dates, perhaps date 2016-06-01 instead of 201606, but I worked with what you have currently... and took advantage that in numeric format, "24 months ago" simply means "subtract 200").
with inputs (linenum, idnum, fiscalyearmonth) as (
select 1, 255, 201605 from dual union all
select 2, 123, 201602 from dual union all
select 3, 255, 201601 from dual union all
select 4, 255, 201210 from dual
)
select linenum, idnum, fiscalyearmonth,
case when fiscalyearmonth
- lag(fiscalyearmonth)
over (partition by idnum order by fiscalyearmonth) < 200
then 'Existing' else 'New' end as flag
from inputs
order by linenum;
LINENUM IDNUM FISCALYEARMONTH FLAG
---------- ---------- --------------- --------
1 255 201605 Existing
2 123 201602 New
3 255 201601 New
4 255 201210 New
Another solution might be to outer Join "DATABASE"."SALES" T4 a second time as T5, wilter the fiscal year via WHERE to < t4.FiscalYear-2. If the Column is NULL, the record is new, if the outer join results in a value, the record is historic.
You can achieve using row_number() function as below... modify as per your need...I assumed 2 years (means previous 24 months from sysdate ).
You can run the sub-queries separately to check how its working.
Select
"REGION"
,"COUNTRY"
,"IDNum"
,"CUSTOMER"
,"BUSSINESS"
,"FISCALYEARMONTH"
,"FISCALYEAR"
,"VALUE"
, ( case when ( TXNNO = 1 or TOTAL_TXN_LAST24MTH = 0 ) then 'New' else 'Existing' end ) as "HISTORICAL_PURCHASE_FLAG" -- if no txn in last 24 month or its first txn then 'new' else 'existing'
from
(
select
SubQry."REGION"
, SubQry."COUNTRY"
, SubQry."IDNum"
, SubQry."CUSTOMER"
, SubQry."BUSSINESS"
, SubQry."FISCALYEARMONTH"
, SUBQRY."FISCALYEAR"
, SUBQRY."VALUE"
, ROW_NUMBER() over (partition by SUBQRY."REGION",SUBQRY."COUNTRY",SUBQRY."IDNum",SUBQRY."CUSTOMER",SUBQRY."BUSSINESS" order by SUBQRY."FISCALYEARMONTH") as TXNNO,
, SUM(case when (TO_NUMBER(TO_CHAR(sysdate,'YYYYMM')) - SUBQRY."FISCALYEARMONTH") < 24 then 1 else 0 end) as TOTAL_TXN_LAST24MTH
From
(
SELECT
T1."REGION"
, T1."COUNTRY"
, T1."IDNum"
, T1."CUSTOMER"
, T1."BUSSINESS"
, T3."FISCALYEARMONTH"
, T3."FISCALYEAR"
, SUM(T4."VALUE") as VALUE
FROM
"DATABASE"."SALES" T4
, "DATABASE"."CUSTOMER" T1
, "DATABASE"."PRODUCT" T2
, "DATABASE"."TIME" T3
WHERE
T4."CUSTOMERID" = T1."CUSTOMERID"
AND T4."PRODUCTID" = T2."PRODUCTID"
AND T4."DATEID" = T3."DATEID"
AND T3."FISCALYEAR" IN ('2016')
AND T1."COUNTRY" IN ('ENGLAND', 'France')
GROUP BY
T1."REGION"
, T1."COUNTRY"
, T1."IDNum"
, T1."CUSTOMER"
, T1."BUSSINESS"
, T3."FISCALYEARMONTH"
, T3."FISCALYEAR"
) SUBQRY
);