De-Dupe lines in CTE based off of one key in sql - sql

I am not really sure on what I need with my issue. In the CTEs below I get an out put that gives me all the columns I want, but I am getting duplicates lines because a member can have two different type of Diagnosis code, What I want is to have one line per Member ID and then along with the DX codes so for example ...
MEMBERID FIRST_NAME BIRTHDATE DIAGNOSIS_CODE
999999999 John 9/9/9999 E11.9
999999999 John 9/9/9999 E79.8
I Want the output to be like this
MEMBERID FIRST_NAME BIRTHDATE DIAGNOSIS_CODE DIAGNOSIS_CODE
999999999 John 9/9/9999 E11.9 E79.8
See now its one line per member, this is my code below and it runs without any issues, I am just trying to get one line per member please. The example above are just for the example not actually in my code but thought it be easier to read the example, rather then my code. any help is greatly appreciated
WITH
Dates as ( Select ADD_MONTHS(TRUNC(sysdate,'MM'),-12) as MONTH1_BEGINDATE,
LAST_DAY(ADD_MONTHS(TRUNC(SYSDATE,'MM'),-1)) MONTH12_LASTDATE
from dual ---- requestor wants a rolling 12 month period
), --select * from Dates
DX AS (Select dx.diag_cd as Diagnosis_code, --- pulling in all members who have Diabetes DX regardless of date span from tab6 in ICUE for AZ
dx.mbr_id
From icue.mbr_diag dx
where dx.diag_cd in ('E08.00','E08.01','E08.10','E08.11','E08.21','E08.22','E08.29','E08.311','E08.319','E08.321',
'E08.329','E08.331','E08.339','E08.341','E08.349','E08.351','E08.352','E08.353','E08.354','E08.355',
'E08.359','E08.36','E08.37','E08.39','E08.40','E08.41','E08.42','E08.43','E08.44','E08.49',
'E08.51','E08.52','E08.59','E08.610','E08.618','E08.620','E08.621','E08.622','E08.628','E08.630',
'E08.638','E08.641','E08.649','E08.65','E08.69','E08.8','E08.9','E10.10','E10.11','E10.21',
'E10.22','E10.29','E10.311','E10.319','E10.321','E10.329','E10.331','E10.339','E10.341','E10.349',
'E10.351','E10.352','E10.353','E10.354','E10.355','E10.359','E10.36','E10.37','E10.39','E10.40',
'E10.41','E10.42','E10.43','E10.44','E10.49','E10.51','E10.52','E10.59','E10.610','E10.618',
'E10.620','E10.621','E10.622','E10.628','E10.630','E10.638','E10.641','E10.649','E10.65','E10.69',
'E10.8','E10.9','E11.00','E11.01','E11.10','E11.11','E11.21','E11.22','E11.29','E11.311',
'E11.319','E11.321','E11.329','E11.331','E11.339','E11.341','E11.349','E11.351','E11.352','E11.353',
'E11.354','E11.355','E11.359','E11.36','E11.37','E11.39','E11.40','E11.41','E11.42','E11.43',
'E11.44','E11.49','E11.51','E11.52','E11.59','E11.610','E11.618','E11.620','E11.621','E11.622',
'E11.628','E11.630','E11.638','E11.641','E11.649','E11.65','E11.69','E11.8', 'E11.9','E13.00',
'E13.01','E13.10','E13.11','E13.21','E13.22','E13.29','E13.311','E13.319','E13.321','E13.329',
'E13.331','E13.339','E13.341','E13.349','E13.351','E13.352','E13.353','E13.354','E13.355','E13.359',
'E13.36','E13.37','E13.39','E13.40','E13.41','E13.42','E13.43','E13.44','E13.49','E13.51',
'E13.52','E13.59','E13.610','E13.618','E13.620','E13.621','E13.622','E13.628','E13.630','E13.638',
'E13.641','E13.649','E13.65','E13.69','E13.8','E13.9') ---- all dx Diabetes code, pulling per request
), --select * From DX
members AS (
Select distinct -- need to dedup by member ID
max(case when d.mbr_id_typ_id = 2 then d.mbr_id_txt end) over (partition by d.mbr_id) as MemberID,
max(case when d.mbr_id_typ_id = 1 then d.mbr_id_txt end) over (partition by d.mbr_id) as SubscriberID,
max(case when d.mbr_id_typ_id = 3 then d.mbr_id_txt end) over (partition by d.mbr_id) as MemberAlternateID,
max(case when d.mbr_id_typ_id = 6 then d.mbr_id_txt end) over (partition by d.mbr_id) as MedicaidRecipientNumber,
mb.fst_nm as first_name,
mb.lst_nm as last_name,
trunc(mb.bth_dt) as birthdate,
dx.Diagnosis_code
from DX dx
inner join dates dd
on 1=1
inner join icue.mbr mb
on dx.mbr_id = mb.mbr_id
inner join icue.mbr_cov c -- pull in dates
on mb.mbr_id = c.mbr_id
inner join icue.mbr_id d -- member identifier
on dx.mbr_id = d.mbr_id
and d.mbr_id_typ_id in ('2','3','1','6')
and c.pol_iss_st_cd ='AZ' ---- Policy state lmiting to AZ only
and (c.lob_typ_id='12' OR c.clm_pltfm_id='A9') ---Community and state
), --select * from members
Members_with_diabetesDX AS (
Select m.*,dd.MONTH1_BEGINDATE, dd.MONTH12_LASTDATE from members m
inner join dates dd on 1=1
) select * from Members_with_diabetesDX

Thanks everyone for your help. I went ahead and used row_number then I criteria off of the Alias I did with ro_number . Below is my code.
WITH
Dates as ( Select ADD_MONTHS(TRUNC(sysdate,'MM'),-12) as MONTH1_BEGINDATE,
LAST_DAY(ADD_MONTHS(TRUNC(SYSDATE,'MM'),-1)) MONTH12_LASTDATE
from dual ---- requestor wants a rolling 12 month period
), --select * from Dates
DX AS (Select dx.diag_cd as Diagnosis_code, --- pulling in all members who have Diabetes DX regardless of date span from tab6 in ICUE for AZ
dx.mbr_id
From icue.mbr_diag dx
where dx.diag_cd in ('E08.00','E08.01','E08.10','E08.11','E08.21','E08.22','E08.29','E08.311','E08.319','E08.321',
'E08.329','E08.331','E08.339','E08.341','E08.349','E08.351','E08.352','E08.353','E08.354','E08.355',
'E08.359','E08.36','E08.37','E08.39','E08.40','E08.41','E08.42','E08.43','E08.44','E08.49',
'E08.51','E08.52','E08.59','E08.610','E08.618','E08.620','E08.621','E08.622','E08.628','E08.630',
'E08.638','E08.641','E08.649','E08.65','E08.69','E08.8','E08.9','E10.10','E10.11','E10.21',
'E10.22','E10.29','E10.311','E10.319','E10.321','E10.329','E10.331','E10.339','E10.341','E10.349',
'E10.351','E10.352','E10.353','E10.354','E10.355','E10.359','E10.36','E10.37','E10.39','E10.40',
'E10.41','E10.42','E10.43','E10.44','E10.49','E10.51','E10.52','E10.59','E10.610','E10.618',
'E10.620','E10.621','E10.622','E10.628','E10.630','E10.638','E10.641','E10.649','E10.65','E10.69',
'E10.8','E10.9','E11.00','E11.01','E11.10','E11.11','E11.21','E11.22','E11.29','E11.311',
'E11.319','E11.321','E11.329','E11.331','E11.339','E11.341','E11.349','E11.351','E11.352','E11.353',
'E11.354','E11.355','E11.359','E11.36','E11.37','E11.39','E11.40','E11.41','E11.42','E11.43',
'E11.44','E11.49','E11.51','E11.52','E11.59','E11.610','E11.618','E11.620','E11.621','E11.622',
'E11.628','E11.630','E11.638','E11.641','E11.649','E11.65','E11.69','E11.8', 'E11.9','E13.00',
'E13.01','E13.10','E13.11','E13.21','E13.22','E13.29','E13.311','E13.319','E13.321','E13.329',
'E13.331','E13.339','E13.341','E13.349','E13.351','E13.352','E13.353','E13.354','E13.355','E13.359',
'E13.36','E13.37','E13.39','E13.40','E13.41','E13.42','E13.43','E13.44','E13.49','E13.51',
'E13.52','E13.59','E13.610','E13.618','E13.620','E13.621','E13.622','E13.628','E13.630','E13.638',
'E13.641','E13.649','E13.65','E13.69','E13.8','E13.9') ---- all dx Diabetes code, pulling per request
), --select * From DX
members AS (
Select distinct -- need to dedup by member ID
max(case when d.mbr_id_typ_id = 2 then d.mbr_id_txt end) over (partition by d.mbr_id) as MemberID,
max(case when d.mbr_id_typ_id = 1 then d.mbr_id_txt end) over (partition by d.mbr_id) as SubscriberID,
max(case when d.mbr_id_typ_id = 3 then d.mbr_id_txt end) over (partition by d.mbr_id) as MemberAlternateID,
max(case when d.mbr_id_typ_id = 6 then d.mbr_id_txt end) over (partition by d.mbr_id) as MedicaidRecipientNumber,
mb.fst_nm as first_name,
mb.lst_nm as last_name,
trunc(mb.bth_dt) as birthdate,
dx.Diagnosis_code
from DX dx
inner join dates d
on 1=1
inner join icue.mbr mb
on dx.mbr_id = mb.mbr_id
--and mb.orig_sys_mbr_id in ('2','3')
inner join icue.mbr_cov c -- pull in dates
on mb.mbr_id = c.mbr_id
inner join icue.mbr_id d -- member identifier
on dx.mbr_id = d.mbr_id
and d.mbr_id_typ_id in ('2','3','1','6')
and c.pol_iss_st_cd ='AZ' ---- Policy state lmiting to AZ only
and (c.lob_typ_id='12' OR c.clm_pltfm_id='A9') ---Community and state
), --select * from members
Members_with_diabetesDX AS (
Select
m.MemberID,
m.SubscriberID,
m.MemberAlternateID,
m.MedicaidRecipientNumber,
m.first_name,
m.last_name,
m.birthdate,
m.Diagnosis_code,
row_number() over (partition by m.MemberID order by m.Diagnosis_code Desc) as Rank,
d.MONTH1_BEGINDATE,
d.MONTH12_LASTDATE
from members m
inner join dates d on 1=1
),-- select * from Members_with_diabetesDX
Final as (
Select
ff.MemberID,
ff.SubscriberID,
ff.MemberAlternateID,
ff.MedicaidRecipientNumber,
ff.first_name,
ff.last_name,
ff.birthdate,
max(case when ff.Rank = 1 then ff.Diagnosis_code end) over (partition by ff.MemberID) as firstdx,
max(case when ff.Rank = 2 then ff.Diagnosis_code end) over (partition by ff.MemberID) as secdx,
max(case when ff.Rank = 3 then ff.Diagnosis_code end) over (partition by ff.MemberID) as thirddx,
max(case when ff.Rank = 4 then ff.Diagnosis_code end) over (partition by ff.MemberID) as fourthdx,
ff.MONTH1_BEGINDATE,
ff.MONTH12_LASTDATE,
row_number() over (partition by ff.MemberID order by ff.Diagnosis_code,ff.SubscriberID,ff.MemberAlternateID,ff.MedicaidRecipientNumber,ff.first_name,ff.last_name,ff.birthdate Desc) as uniquerow
from Members_with_diabetesDX ff
) select * from Final where uniquerow ='1'

Related

SQL Case When Slowing Down Query

What I'm looking to do is quantify the total value of purchases and the number of months in which a purchase was made within three different timeframes by account. I only want to look at accounts who made a purchase between 1-1-2020 and 4-1-2021.
I'm wondering if there is a more streamlined way to pull in the fields I'm creating using CASE WHEN below (maybe through a series of queries to create the calculations and the left joining?). This query is taking extremely long to pull back, so I'd like to enhance this code where I can. All of my code and desired output is listed below. Thank you!
Creating a temporary table to pull account numbers:
DROP TABLE IF EXISTS #accounts
SELECT DISTINCT s.account_no, c.code, c.code_desc
INTO #accounts
FROM sales AS s
LEFT JOIN customer AS c ON s.account_no = c.account_no
WHERE s.tran_date BETWEEN '2020-01-01' AND '2021-04-01'
GROUP BY s.account_no, c.code, c.code_desc;
Confirming row counts:
SELECT COUNT (*)
FROM #accounts
ORDER BY account_no;
Creating Sales and Sales period count columns for three timeframes:
SELECT
s.account_no, c.code, c.code_desc
SUM(CASE
WHEN s.tran_date BETWEEN '2020-01-01' AND '2021-04-01'
THEN VALUE_USD
END) AS Total_Spend_Pre,
SUM(CASE
WHEN s.tran_date BETWEEN '2021-04-01' AND '2022-03-31'
THEN VALUE_USD
END) Total_Spend_During,
SUM(CASE
WHEN s.tran_date > '2022-04-01'
THEN VALUE_USD
END) Total_Spend_Post,
COUNT(DISTINCT CASE WHEN s.tran_date BETWEEN '2020-01-01' AND '2021-04-01' THEN CONCAT(s.bk_month, s.bk_year) END) Pre_Periods,
COUNT(DISTINCT CASE WHEN s.tran_date BETWEEN '2021-04-01' AND '2022-03-31' THEN CONCAT(s.bk_month, s.bk_year) END) During_Periods,
COUNT(DISTINCT CASE WHEN s.tran_date > '2022-04-01' THEN CONCAT(s.bk_month, s.bk_year) END) Post_Periods
FROM
sales AS s
LEFT JOIN
customer AS c ON s.account_no = c.account_no
WHERE
c.account_no IN (SELECT DISTINCT account_no
FROM #accounts)
GROUP BY
s.account_no, c.code, c.code_desc;
Desired output:
account_no
code
code_desc
Total_Spend_Pre
Total_Spend_During
Total_Spend_Post
Pre_Periods
During_Periods
Post_Periods
25
1234
OTHER
1000
2005
500
2
14
5
11
5678
PC
500
100
2220
5
11
2
You may use your date ranges to join with dataset, and 'Tag' your result like below, this will result in 3 rows, for each group. If you need them in a single row, have PIVOTE over it
;With DateRanges AS (
SELECT CAST('2020-01-01' AS DATE) StartDate, CAST('2021-04-01' AS DATE) EndDate, 'Pre' Tag UNION
SELECT '2021-04-01', '2022-03-31', 'During' UNION
SELECT '2022-04-01', Null, 'Post'
)
SELECT s.account_no, c.code, c.code_desc, d.Tag,
SUM(VALUE_USD) AS Total_Spend,
COUNT(DISTINCT CONCAT(s.bk_month, s.bk_year)) RecordCount
FROM sales as s
LEFT JOIN customer as c
INNER JOIN DateRanges D ON s.tran_date BETWEEN D.StartDate AND ISNULL(D.EndDate,s.tran_date)
ON s.account_no = c.account_no
WHERE c.account_no IN (SELECT DISTINCT account_no FROM #accounts)
GROUP BY s.account_no, c.code, c.code_desc;
with [cte_accountActivityPeriods] as (
select [PeriodOrdinal] = 1, [PeriodName] = 'Total Spend Pre', [PeriodStart] = convert(date,'2020-01-01',23) , [PeriodFinish] = convert(date,'2021-03-31',23) union
select [PeriodOrdinal] = 2, [PeriodName] = 'Total Spend During', [PeriodStart] = convert(date,'2021-04-01',23) , [PeriodFinish] = convert(date,'2022-03-31',23) union
select [PeriodOrdinal] = 3, [PeriodName] = 'Total Spend Post', [PeriodStart] = convert(date,'2022-04-01',23) , [PeriodFinish] = convert(date,'9999-12-31',23)
)
, [cte_allsalesForActivityPeriod]
SELECT s.account_no, bk_month, bk_year, [PeriodOrdinal], s.tran_date, s.value_usd
FROM sales as s
cross join [cte_accountActivityPeriods]
on s.[tran_date] between [cte_ActivityPeriods].[PeriodStart] and [cte_ActivityPeriods].[PeriodFinish]
)
, [cte_uniqueAccounts] as ( /*Unique and qualifying Accounts*/
select distinct account_no from [cte_allsalesForActivityPeriod]
inner join #accounts accs on accs.[account_no] = [cte_allsalesForActivityPeriod].[account_no]
)
, [cte_AllSalesAggregatedByPeriod] as (
select account_no, [PeriodOrdinal], bk_month, bk_year, [PeriodTotalSpend] = sum([value_usd])
from [cte_allsalesForActivityPeriod]
group by s.account_no, [PeriodOrdinal], bk_month, bk_year
)
, [cte_PeriodAnalysis] as (
select account_no, [PeriodOrdinal], [ActivePeriods] = count(distinct concat(bk_month, bk_year))
from [cte_AllSalesAggregatedByPeriod]
group by s.account_no, [PeriodOrdinal]
)
, [cte_pivot_clumsily] as (
/* Aggregations already done - so simple pivot */
select [cte_uniqueAccounts].[account_no]
, [Total_Spend_Pre] = case when [SaleVal].[PeriodOrdinal] in (1) then [SaleVal].[PeriodTotalSpend] else 0 end
, [Total_Spend_During] = case when [SaleVal].[PeriodOrdinal] in (2) then [SaleVal].[PeriodTotalSpend] else 0 end
, [Total_Spend_Post] = case when [SaleVal].[PeriodOrdinal] in (3) then [SaleVal].[PeriodTotalSpend] else 0 end
, [Pre_Periods] = case when [SalePrd].[PeriodOrdinal] in (1) then [SalePrd].[ActivePeriods] else 0 end
, [During_Periods] = case when [SalePrd].[PeriodOrdinal] in (2) then [SalePrd].[ActivePeriods] else 0 end
, [Post_Periods] = case when [SalePrd].[PeriodOrdinal] in (3) then [SalePrd].[ActivePeriods] else 0 end
from [cte_uniqueAccounts]
left join [cte_AllSalesAggregatedByPeriod] [SaleVal] on [SaleVal].[account_no] = [cte_uniqueAccounts].[account_no]
left join [cte_PeriodAnalysis] [SalePrd] on [SalePrd].[account_no] = [cte_uniqueAccounts].[account_no]
)
select c.code, c.code_desc, [cte_pivot_clumsily].*
from [cte_pivot_clumsily]
LEFT JOIN customer as c
ON [cte_pivot_clumsily].account_no = c.account_no

oracle sql get transactions between the period

I have 3 tables in oracle sql namely investor, share and transaction.
I am trying to get new investors invested in any shares for a certain period. As they are the new investor, there should not be a transaction in the transaction table for that investor against that share prior to the search period.
For the transaction table with the following records:
Id TranDt InvCode ShareCode
1 2020-01-01 00:00:00.000 inv1 S1
2 2019-04-01 00:00:00.000 inv1 S1
3 2020-04-01 00:00:00.000 inv1 S1
4 2021-03-06 11:50:20.560 inv2 S2
5 2020-04-01 00:00:00.000 inv3 S1
For the search period between 2020-01-01 and 2020-05-01, I should get the output as
5 2020-04-01 00:00:00.000 inv3 S1
Though there are transactions for inv1 in the table for that period, there is also a transaction prior to the search period, so that shouldn't be included as it's not considered as new investor within the search period.
Below query is working but it's really taking ages to return the results calling from c# code leading to timeout issues. Is there anything we can do to refine to get the results quicker?
WITH
INVESTORS AS
(
SELECT I.INVCODE FROM INVESTOR I WHERE I.CLOSED IS NULL)
),
SHARES AS
(
SELECT S.SHARECODE FROM SHARE S WHERE S.DORMANT IS NULL))
),
SHARES_IN_PERIOD AS
(
SELECT DISTINCT
T.INVCODE,
T.SHARECODE,
T.TYPE
FROM TRANSACTION T
JOIN INVESTORS I ON T.INVCODE = I.INVCODE
JOIN SHARES S ON T.SHARECODE = S.SHARECODE
WHERE T.TRANDT >= :startDate AND T.TRANDT <= :endDate
),
PREVIOUS_SHARES AS
(
SELECT DISTINCT
T.INVCODE,
T.SHARECODE,
T.TYPE
FROM TRANSACTION T
JOIN INVESTORS I ON T.INVCODE = I.INVCODE
JOIN SHARES S ON T.TRSTCODE = S.TRSTCODE
WHERE T.TRANDT < :startDate
)
SELECT
DISTINCT
SP.INVCODE AS InvestorCode,
SP.SHARECODE AS ShareCode,
SP.TYPE AS ShareType
FROM SHARES_IN_PERIOD SP
WHERE (SP.INVCODE, SP.SHARECODE, SP.TYPE) NOT IN
(
SELECT
PS.INVCODE,
PS.SHARECODE,
PS.TYPE
FROM PREVIOUS_SHARES PS
)
With the suggestion given by #Gordon Linoff, I tried following options (for all the shares I need) but they are taking long time too. Transaction table is over 32 million rows.
1.
WITH
SHARES AS
(
SELECT S.SHARECODE FROM SHARE S WHERE S.DORMANT IS NULL))
)
select t.invcode, t.sharecode, t.type
from (select t.*,
row_number() over (partition by invcode, sharecode, type order by trandt)
as seqnum
from transactions t
) t
join shares s on s.sharecode = t.sharecode
where seqnum = 1 and
t.trandt >= date '2020-01-01' and
t.trandt < date '2020-05-01';
WITH
INVESTORS AS
(
SELECT I.INVCODE FROM INVESTOR I WHERE I.CLOSED IS NULL)
),
SHARES AS
(
SELECT S.SHARECODE FROM SHARE S WHERE S.DORMANT IS NULL))
)
select t.invcode, t.sharecode, t.type
from (select t.*,
row_number() over (partition by invcode, sharecode, type order by trandt)
as seqnum
from transactions t
) t
join investors i on i.invcode = t.invcode
join shares s on s.sharecode = t.sharecode
where seqnum = 1 and
t.trandt >= date '2020-01-01' and
t.trandt < date '2020-05-01';
select t.invcode, t.sharecode, t.type
from (select t.*,
row_number() over (partition by invcode, sharecode, type order by trandt)
as seqnum
from transactions t
) t
where seqnum = 1 and
t.sharecode IN (SELECT S.SHARECODE FROM SHARE S WHERE S.DORMANT IS NULL)))
and
t.trandt >= date '2020-01-01' and
t.trandt < date '2020-05-01';
If you want to know if the first record in transactions for a share is during a period, you can use window functions:
select t.*
from (select t.*,
row_number() over (partition by invcode, sharecode order by trandt) as seqnum
from transactions t
) t
where seqnum = 1 and
t.sharecode = :sharecode and
t.trandt >= date '2020-01-01' and
t.trandt < date '2020-05-01';
For performance for this code, you want an index on transactions(invcode, sharecode, trandate).

Perform a Series of Calculations on a Multiple CTE Table

Can't seem to figure out the formula for performing a series of functions on my query. I need to subtract the figures in the DIF column depending on the STAT code. I need to perform the same series of functions in every case. STAT I0099 MINUS E0002, this result will always be the denominator. After this I need to take each of the other lines in the table and divide them by this result.
1st (2811-98), 2nd E0013 (52/(2811-98)) 3rd E0019 (405/(2811-98)) 4th E0004 (2256/(2811-98) End.
I've tried adding rollup and a couple of others things, I saw on here, but none were successful.
WITH i_stat_cte
AS
(
SELECT ROW_NUMBER() OVER(partition by STAT Order by UDATE ) as
Rn,JCDS_SOGR.OBJNR, JCDS_SOGR.STAT,JCDS_SOGR.UDATE,JCDS_SOGR.CHGNR,JCDS_SOGR.CDTCODE,JCDS_SOGR.CHIND,JCDS_SOGR.INACT,JCDS_SOGR.TCODE,TJ02T.TXT30, EQUI.BAUJJ as "Year", T370K_T.EARTX as Model,
LAG(UDATE) OVER(partition by STAT Order by UDATE ) As PrevUDate,
COUNT(*) OVER(partition by STAT) As [Count]
from JCDS_SOGR
Join TJ02T on JCDS_SOGR.STAT = TJ02T.ISTAT
Join EQUI on JCDS_SOGR.OBJNR = EQUI.OBJNR
Join T370K_T on equi.EQART = T370K_T.EQART
where jcds_sogr.OBJNR = 'IE000000000010003137'
and TJ02T.SPRAS = 'E'
)
,
e_stat_cte
AS
(
SELECT ROW_NUMBER() OVER(partition by STAT Order by UDATE ) as Rn, JCDS_SOGR.OBJNR, JCDS_SOGR.STAT,JCDS_SOGR.UDATE,JCDS_SOGR.CHGNR,JCDS_SOGR.CDTCODE,JCDS_SOGR.CHIND,JCDS_SOGR.INACT,JCDS_SOGR.TCODE,TJ30T.TXT30, EQUI.BAUJJ as "Year", T370K_T.EARTX as Model,
LAG(UDATE) OVER(partition by STAT Order by UDATE ) As PrevUDate,
COUNT(*) OVER(partition by STAT) As [Count], TJ30T.MANDT as Client
from JCDS_SOGR
Join TJ30T on JCDS_SOGR.STAT = TJ30T.ESTAT
Join EQUI on JCDS_SOGR.OBJNR = EQUI.OBJNR
Join T370K_T on equi.EQART = T370K_T.EQART
where jcds_sogr.OBJNR = 'IE000000000010003137'
and TJ30T.SPRAS = 'E'AND TJ30T.MANDT='400'
AND TJ30T.STSMA = 'VEHICLE' AND T370K_T.MANDT = '400')
SELECT Max(rn) As [Count],
OBJNR,Year, Model, STAT,TXT30,
SUM(CASE WHEN rn%2=0 THEN DATEDIFF(d,PrevUDate,UDATE)
WHEN rn=[Count] THEN DATEDIFF(d,UDATE,getDate())
ELSE 0 END) as DIF
from i_stat_cte
Group BY OBJNR, STAT,TXT30, Year, Model
UNION
SELECT Max(rn) As [Count],
OBJNR,Year, Model, STAT,TXT30,
SUM(CASE WHEN rn%2=0 THEN DATEDIFF(d,PrevUDate,UDATE)
WHEN rn=[Count] THEN DATEDIFF(d,UDATE,getDate())
ELSE 0 END) as DIF
from e_stat_cte
Group BY OBJNR, STAT,TXT30, Year, Model
EXPECTED RESULTS
Count OBJNR Year Model STAT TXT30 DIF Avail | Calculations
1 IE000000000010003137 2011 Orion I0099 Avail 2810
2 IE000000000010003137 2011 Orion E0002 Await 98
4 IE000000000010003137 2011 Orion E0013 Non Op 52 .0191740 = (52/(2810-98))
4 IE000000000010003137 2011 Orion E0019 OperBk 405 .1493363 = (405/(2810-98))
7 IE000000000010003137 2011 Orion E0004 Oper 2255 .8314897 = (2255/(2810-98))
--The code below is a conversion of your code from CTE to temp tables.
--Hopefully you can perform better diagnostics on it. Just evaluate each of the data you are producing on your last query. I think the UNION is a bit sloppy. Are you sure it's really a UNION and not a UNION ALL?
DROP TABLE IF EXISTS #i_stat_cte
SELECT ROW_NUMBER() OVER(partition by STAT Order by UDATE ) as
Rn,JCDS_SOGR.OBJNR, JCDS_SOGR.STAT,JCDS_SOGR.UDATE,JCDS_SOGR.CHGNR,JCDS_SOGR.CDTCODE,JCDS_SOGR.CHIND,JCDS_SOGR.INACT,JCDS_SOGR.TCODE,TJ02T.TXT30, EQUI.BAUJJ as "Year", T370K_T.EARTX as Model,
LAG(UDATE) OVER(partition by STAT Order by UDATE ) As PrevUDate,
COUNT(*) OVER(partition by STAT) As [Count]
INTO #i_stat_cte
from JCDS_SOGR
Join TJ02T on JCDS_SOGR.STAT = TJ02T.ISTAT
Join EQUI on JCDS_SOGR.OBJNR = EQUI.OBJNR
Join T370K_T on equi.EQART = T370K_T.EQART
where jcds_sogr.OBJNR = 'IE000000000010003137'
and TJ02T.SPRAS = 'E'
DROP TABLE IF EXISTS #e_stat_cte
SELECT ROW_NUMBER() OVER(partition by STAT Order by UDATE ) as Rn, JCDS_SOGR.OBJNR, JCDS_SOGR.STAT,JCDS_SOGR.UDATE,JCDS_SOGR.CHGNR,JCDS_SOGR.CDTCODE,JCDS_SOGR.CHIND,JCDS_SOGR.INACT,JCDS_SOGR.TCODE,TJ30T.TXT30, EQUI.BAUJJ as "Year", T370K_T.EARTX as Model,
LAG(UDATE) OVER(partition by STAT Order by UDATE ) As PrevUDate,
COUNT(*) OVER(partition by STAT) As [Count], TJ30T.MANDT as Client
INTO #e_stat_cte
from JCDS_SOGR
Join TJ30T on JCDS_SOGR.STAT = TJ30T.ESTAT
Join EQUI on JCDS_SOGR.OBJNR = EQUI.OBJNR
Join T370K_T on equi.EQART = T370K_T.EQART
where jcds_sogr.OBJNR = 'IE000000000010003137'
and TJ30T.SPRAS = 'E'AND TJ30T.MANDT='400'
AND TJ30T.STSMA = 'VEHICLE' AND T370K_T.MANDT = '400'
-- VERIFY YOU GET WHAT YOU EXPECT
select * from #i_stat_cte
-- VERIFY YOU GET WHAT YOU EXPECT
select * from #e_stat_cte
-- VERIFY YOU GET WHAT YOU EXPECT
SELECT Max(rn) As [Count],
OBJNR,Year, Model, STAT,TXT30,
SUM(CASE WHEN rn%2=0 THEN DATEDIFF(d,PrevUDate,UDATE)
WHEN rn=[Count] THEN DATEDIFF(d,UDATE,getDate())
ELSE 0 END) as DIF
from #i_stat_cte
Group BY OBJNR, STAT,TXT30, Year, Model
--UNION
-- VERIFY YOU GET WHAT YOU EXPECT
SELECT Max(rn) As [Count],
OBJNR,Year, Model, STAT,TXT30,
SUM(CASE WHEN rn%2=0 THEN DATEDIFF(d,PrevUDate,UDATE)
WHEN rn=[Count] THEN DATEDIFF(d,UDATE,getDate())
ELSE 0 END) as DIF
from #e_stat_cte
Group BY OBJNR, STAT,TXT30, Year, Model

Full Outer Join, Coalesce, and Group By (Oh My!)

I'm going to ask this in two parts, because my logic may be way off, and if so, the syntax doesn't really matter.
I have 10 queries. Each query returns month, supplier, and count(some metric). The queries use various tables, joins, etc. Not all month/supplier combinations exist in the output for each query. I would like to combine these into a single data set that can be exported and pivoted on in Excel.
I'd like the output to look like this:
Month | Supplier | Metric1 |Metric2 |..| Metric 10
2018-01 | Supp1 | _value_ | _value_ |...| _value_ |
2018-01 | Supp2 | NULL | _value_ |...| NULL
What is the best / easiest / most efficient way to accomplish this?
I've tried various methods to accomplish the above, but I can't seem to get the syntax quite right. I wanted to make a very simple test case and build upon it, but I only have select privileges on the db, so I am unable to test it out. I was able to create a query that at least doesn't result in any squiggly red error lines, but applying the same logic to the bigger problem doesn't work.
This is what I've got:
create table test1(name varchar(20),credit int);
insert into test1 (name, credit) values ('Ed',1),('Ann',1),('Jim',1),('Ed',1),('Ann',1);
create table test2 (name varchar(10), debit int);
insert into test2 (name, debit) values ('Ann',1),('Sue',1),('Sue',1),('Sue',1);
select
coalesce(a.name, b.name) as name,
cred,
deb
from
(select name, count(credit) as cred
from test1
group by name) a
full outer join
(select name, count(debit) as deb
from test2
group by name) b on
a.name =b.name;
Am I headed down the right path?
UPDATE: Based on Gordon's input, I tried this on the first two queries:
select Month, Supp,
sum(case when which = 1 then metric end) as Exceptions,
sum(case when which = 2 then metric end) as BackOrders
from (
(
select Month, Supp, metric, 1 as which
from (
select (convert(char(4),E.PostDateTime,120)+'-'+convert(char(2),E.PostDateTime,101)) as Month, E.TradingPartner as Supp, count(distinct(E.excNum)) as metric
from db..TrexcMangr E
where (E.DSHERep in ('AVR','BTB') OR E.ReleasedBy in ('AVR','BTB')) AND year(E.PostDateTime) >= '2018'
) a
)
union all
(
select Month, Supp, metric, 2 as which
from (
select (convert(char(4),T.UpdatedDateTime,120)+'-'+convert(char(2),T.UpdatedDateTime,101)) as Month, P.Supplier as Supp, count(*) as metric
from db1..trordertext T
inner join mdid_Tran..trOrderPO P on P.PONum = T.RefNum
where T.TextType = 'BO' AND (T.CreatedBy in ('AVR','BTB') OR T.UpdatedBy in ('AVR','BTB')) AND year(UpdatedDateTime) >=2018
) b
)
) q
group by Month, Supp
... but I'm getting a group by error.
One method uses union all and group by:
select month, supplier,
sum(case when which = 1 then metric end) as metric_01,
sum(case when which = 2 then metric end) as metric_02,
. . .
from ((select Month, Supplier, Metric, 1 as which
from (<query1>) q
. . .
) union all
(select Month, Supplier, Metric, 2 as which
from (<query2>) q
. . .
) union all
. . .
) q
group by month, supplier;
SELECT
CalendarMonthStart,
Supp,
SUM(CASE WHEN metric_id = 1 THEN metric END) as Exceptions,
SUM(CASE WHEN metric_id = 2 THEN metric END) as BackOrders
FROM
(
SELECT
DATEADD(month, DATEDIFF(month, 0, E.PostDateTime), 0) AS CalendarMonthStart,
E.TradingPartner AS Supp,
COUNT(DISTINCT(E.excNum)) AS metric,
1 AS metric_id
FROM
db..TrexcMangr E
WHERE
( E.DSHERep in ('AVR','BTB')
OR E.ReleasedBy in ('AVR','BTB')
)
AND E.PostDateTime >= '2018-01-01'
GROUP BY
1, 2
UNION ALL
SELECT
DATEADD(month, DATEDIFF(month, 0, T.UpdatedDateTime), 0) AS CalendarMonthStart,
T.UpdatedDateTime,
P.Supplier AS Supp,
COUNT(*) AS metric,
2 AS metric_id
FROM
db1..trordertext T
INNER JOIN
mdid_Tran..trOrderPO P
ON P.PONum = T.RefNum
WHERE
( T.CreatedBy in ('AVR','BTB')
OR T.UpdatedBy in ('AVR','BTB')
)
AND T.TextType = 'BO'
AND T.UpdatedDateTime >= '2018-01-01'
GROUP BY
1, 2
)
combined
GROUP BY
CalendarMonthStart,
Supp

Selecting the Max Date From Multiple Tables

any help would be so incredibly appreciated. I am trying to select the last activity date from a group of tables. The tables include Entry Date, Note date, payment date, and Claim Date. I would like to return only the max value from all these dates. Furthermore I only want records where there has been no activity for over 45 days. I am currently using the following SQL to bring all the dates in then using calculated fields in EXCEL to figure the rest out. Is it possible to do this all with SQL?
Thanks in advance.
SELECT xrxTrnLgr.PatId, xrxTrnLgr.Balance,
Max(xrxPatNotes.NoteDate) AS 'Max of NoteDate',
Max(xrxTrnIcf.PostDate) AS 'Max of IcfPostDate',
Max(xrxPat.EntryDate) AS 'Entry Date',
Max(xrxPat.Coverage) AS 'Coverage',
Max(xrxTrnPay.PostDate) AS 'Last Payment'
FROM xrxTrnLgr
LEFT OUTER JOIN xrxPatNotes ON xrxTrnLgr.PatId = xrxPatNotes.PatId
LEFT OUTER JOIN xrxTrnIcf ON xrxTrnLgr.PatId = xrxTrnIcf.PatId
LEFT OUTER JOIN xrxPat ON xrxTrnLgr.PatId = xrxPat.PatId
LEFT OUTER JOIN xrxTrnPay ON xrxTrnLgr.PatId = xrxTrnPay.PatId
GROUP BY xrxTrnLgr.PatId, xrxTrnLgr.Balance
HAVING (xrxTrnLgr.Balance>$.01)
I think this might do it all in SQL:
select t.patid, t.balance,
max(case when which = 'note' then thedate end) as note,
max(case when which = 'post' then thedate end) as post,
max(case when which = 'entry' then thedate end) as entry,
max(case when which = 'coverage' then thedate end) as coverage,
max(case when which = 'lastPayment' then thedate end) as lastPayment
from xrxTrnLgr t left join
((select patid, notedate as thedate, 'note' as which
from xrxPatNotes
) union all
(select patid, postdate, 'post'
from xrxtrnIcf
) union all
(select patid, EntryDate, 'entry'
from xrxPat
) union all
(select paid, Coverage, 'coverage'
from xrxPat.Coverage
) union all
(select patid, PostDate, 'LastPayment'
from xrxTrnPay.PostDate
)
) d
on t.patid = d.patid
group by t.patid, t.balance
having min(now() - thedate) >= 45