SQL Server 2008 Flatten Rows - sql-server

I need to flatten a record set that originally has 4 rows per user to be 1 row. I started using the PIVOT functionality but there are 2 fields that need to be flatten (and the pivot wasn't working as expected ).
The current data structure:
ContactEmail Scenario TRE Updated_On
-------------------------------------------------------------
email#email.com WTD 0.9785 2015-05-12 22:35:14.993
email#email.com MTD 0.9817 2015-05-12 22:35:57.780
email#email.com QTD 0.9542 2015-05-12 23:16:35.227
email#email.com YTD 0.9522 2015-05-12 23:39:56.533
The result should be:
ContactEmail WTD_TRE WTD_TRE_Updated MTD_TRE MTD_TRE_Updated QTD_TRE QTD_TRE_Updated YTD_TRE YTD_TRE_Updated
--------------------------------------------------------------------------------------------------------------------
email#email.com 0.9785 2015-05-12 0.9817 2015-05-12 0.9542 2015-05-12 0.9522 2015-05-12
If you're curious about the PIVOT I tried, here it is (the TRE_* were all null)
SELECT *
FROM (SELECT ContactEmail, Round((ISNULL(TRE, 0) * 100), 1) AS "TRE", Scenario, Updated_On
FROM [server].[db].[schema].[table]) AS TREData
PIVOT
(
SUM(TRE)
FOR Scenario
IN ([TRE_WTD],[TRE_MTD],[TRE_QTD],[TRE_YTD])
) AS PivotTable;

Create two pivot queries and join them...
WITH CurrentDataStructure as (
SELECT 'email#email.com' ContactEmail,
'WTD' Scenario,
0.9785 TRE,
'2015-05-12 22:35:14.993' Updated_On
UNION SELECT 'email#email.com', 'MTD', 0.9817, '2015-05-12 22:35:57.780'
UNION SELECT 'email#email.com', 'QTD', 0.9542, '2015-05-12 23:16:35.227'
UNION SELECT 'email#email.com', 'YTD', 0.9522, '2015-05-12 23:39:56.533'
), TREData as (
SELECT ContactEmail, Round((ISNULL(TRE, 0) * 100), 1) TRE, Scenario, Updated_On
FROM CurrentDataStructure
), TREs AS (
SELECT *
FROM (SELECT ContactEmail, Scenario, TRE FROM TREData) TREData
PIVOT
(
SUM(TRE)
FOR Scenario
IN ([WTD],[MTD],[QTD],[YTD])
) PivotTable
), TREsUpdated AS (
SELECT *
FROM (SELECT ContactEmail, Scenario, Updated_On FROM TREData) TREData
PIVOT
(
MAX(Updated_On)
FOR Scenario
IN ([WTD],[MTD],[QTD],[YTD])
) PivotTable
)
SELECT t.ContactEmail,
t.WTD WTD_TRE, u.WTD WTD_TRE_Updated,
t.MTD MTD_TRE, u.MTD MTD_TRE_Updated,
t.QTD QTD_TRE, u.QTD QTD_TRE_Updated,
t.YTD YTD_TRE, u.YTD YTD_TRE_Updated
FROM TREs as t
INNER JOIN
TREsUpdated as u
ON t.ContactEmail = u.ContactEmail
This is tested through and should run just like it is.

Related

SQL unpivot of multiple columns

I would like the following wide table to be unpivotted but only where a user has a true value against the field, along with the appropriate date.
Current State:
CUSTOMER_ID
First_Party_Email
Third_Party_Email
First_Party_Email_Date
Third_Party_Email_Date
40011111
1
1
2021-01-22 04:38:00.000
2021-01-17 06:38:00.000
50022222
NULL
1
NULL
2021-01-18 04:38:00.000
80066666
1
NULL
2021-01-24 05:38:00.000
NULL
_______________
_______________________
_______________________
_______________________________
_______________________________
Required State:
Customer_ID
Type
Value
Date
40011111
First_Party_Email
1
22/01/2021 04:38
40011111
Third_Party_Email
1
17/01/2021 06:38
50022222
Third_Party_Email
1
18/01/2021 04:38
80066666
First_Party_Email
1
24/01/2021 05:38
_______________________________________________________________________
Associated query to create table and my attempt that doesn't work:
create table Permissions_Obtained
(Customer_ID bigint
,First_Party_Email bit
,Third_Party_Email bit
,First_Party_Email_Date datetime
,Third_Party_Email_Date datetime
)
insert into Permissions_Obtained
(Customer_ID
,First_Party_Email
,Third_Party_Email
,First_Party_Email_Date
,Third_Party_Email_Date
)
VALUES
(40011111, 1, 1, '2021-01-22 04:38', '2021-01-17 06:38'),
(50022222, NULL, 1, NULL, '2021-01-18 04:38'),
(80066666, 1, NULL, '2021-01-24 05:38', null)
select *
from Permissions_Obtained
select
customer_id, Permission
from Permissions_Obtained
unpivot
(
GivenPermission
for Permission in (
First_Party_Email, Third_Party_Email
)
) unpiv1,
unpivot
(
GivenPermissionDate
for PermissionDate in (
First_Party_Email_Date, Third_Party_Email_Date
)
) unpiv2
where GivenPermission = 1
--drop table Permissions_Obtained
Any help would be massively appreciated. TIA
You cannot have multiple unpivots at the same time. Instead you can use Cross Apply or Inner join or union, union all or kind of joins depending on your requirement. I have added a sample answer for this using join and unpivot.
SELECT
unpvt.Customer_ID
, [Type]
, ISNULL(po.First_Party_Email ,po.Third_Party_Email) AS [Value]
,CASE WHEN unpvt.Type = 'First_Party_Email' THEN po.First_Party_Email_Date
ELSE po.Third_Party_Email_Date
END AS [Date]
FROM
(
SELECT
Customer_ID, First_Party_Email , Third_Party_Email
FROM Permissions_Obtained
) p
UNPIVOT
( [Value] FOR [Type] IN
(First_Party_Email , Third_Party_Email )
)AS unpvt
INNER JOIN Permissions_Obtained [po]
on [po].Customer_ID = unpvt.Customer_ID
When un-pivoting multiple columns, CROSS APPLY (VALUES is often the easiest and most effective solution.
It creates a virtual table per-row of the previous table, and therefore un-pivots it into separate rows.
SELECT
p.Customer_Id,
v.[Type],
v.Value,
v.Date
FROM Permissions_Obtained p
CROSS APPLY (VALUES
('First_Party_Email', p.First_Party_Email, p.First_Party_Email_Date),
('Third_Party_Email', p.Third_Party_Email, p.Third_Party_Email_Date)
) v([Type], Value, Date)
where v.Value IS NOT NULL;

Find lowest and highest values split into rows from a single string of concatenated values

This is a follow-up to my question here: in which I got an excellent answer for that question provided by uzi. I however noticed that a new Company, Company3 also used single data Points, such as account 6000 which does not follow the manner of the previous companies which makes uzi's recursive cte not applicable.
As such I feel like it is required to alter the question, but I Believe that this complication would issue a new question rather than an edit on my previous one due to having a great impact of the solution.
I need to read data from an Excel workbook, where data is stored in this manner:
Company Accounts
Company1 (#3000...#3999)
Company2 (#4000..#4019)+(#4021..#4024)
Company3 (#5000..#5001)+#6000+(#6005..#6010)
I believe that due to some companies, such as Company3 having single values of accounts such as #6000 that I need to, in this step, create a result set of the following appearence:
Company FirstAcc LastAcc
Company1 3000 3999
Company2 4000 4019
Company2 4021 4024
Company3 5000 5001
Company3 6000 NULL
Company3 6005 6010
I will then use this table and JOIN it with a table of only integers to get the appearance of the final table such as the one in my linked question.
Does anyone have any ideas?
A good t-sql splitter function makes this quite simple; I suggest delimitedSplit8k. This will perform significantly better than a recursive CTE too. First the sample data:
-- your sample data
if object_id('tempdb..#yourtable') is not null drop table #yourtable;
create table #yourtable (company varchar(100), accounts varchar(8000));
insert #yourtable values ('Company1','(#3000...#3999)'),
('Company2','(#4000..#4019)+(#4021..#4024)'),('Company3','(#5000..#5001)+#6000+(#6005..#6010)');
and the solution:
select
company,
firstAcc = max(case when split2.item not like '%)' then clean.Item end),
lastAcc = max(case when split2.item like '%)' then clean.Item end)
from #yourtable t
cross apply dbo.delimitedSplit8K(accounts, '+') split1
cross apply dbo.delimitedSplit8K(split1.Item, '.') split2
cross apply (values (replace(replace(split2.Item,')',''),'(',''))) clean(item)
where split2.item > ''
group by split1.Item, company;
Results:
company firstAcc lastAcc
--------- ---------- --------------
Company1 #3000 #3999
Company2 #4000 #4019
Company2 #4021 #4024
Company3 #6000 NULL
Company3 #5000 #5001
Company3 #6005 #6010
I believe that list (#6005..#6010) is represented like #6005#6006#6007#6008#6009#6010 in your Excel file. Try this query if that is true and there are no gaps
with cte as (
select
company, replace(replace(replace(accounts,'(',''),')',''),'+','')+'#' accounts
from
(values ('company 1','#3000#3001#3002#3003'),('company 2','(#4000#4001)+(#4021#4022)'),('company 3','(#5000#5001)+#6000+(#6005#6006)')) data(company, accounts)
)
, rcte as (
select
company, stuff(accounts, ind1, ind2 - ind1, '') acc, substring(accounts, ind1 + 1, ind2 - ind1 - 1) accounts
from
cte
cross apply (select charindex('#', accounts) ind1) ca
cross apply (select charindex('#', accounts, ind1 + 1) ind2) cb
union all
select
company, stuff(acc, ind1, ind2 - ind1, ''), substring(acc, ind1 + 1, ind2 - ind1 - 1)
from
rcte
cross apply (select charindex('#', acc) ind1) ca
cross apply (select charindex('#', acc, ind1 + 1) ind2) cb
where
len(acc)>1
)
select
company, min(accounts) FirstAcc, case when max(accounts) =min(accounts) then null else max(accounts) end LastAcc
from (
select
company, accounts, accounts - row_number() over (partition by company order by accounts) group_
from
rcte
) t
group by company, group_
option (maxrecursion 0)
I made a little editing to #uzi solution from the other question, in which i added three other CTE's and used windows function like LEAD() and ROW_NUMBER() to solve the problem. I don't know if there is a simpler solution, but i think this is working good.
with cte as (
select
company, replace(replace(replace(accounts,'(',''),')',''),'+','')+'#' accounts
from
(values ('company 1','#3000..#3999'),('company 2','(#4000..#4019)+(#4021..#4024)'),('company 3','(#5000..#5001)+#6000+(#6005..#6010)')) data(company, accounts)
)
, rcte as (
select
company, stuff(accounts, ind1, ind2 - ind1, '') acc, substring(accounts, ind1 + 1, ind2 - ind1 - 1) accounts
from
cte
cross apply (select charindex('#', accounts) ind1) ca
cross apply (select charindex('#', accounts, ind1 + 1) ind2) cb
union all
select
company, stuff(acc, ind1, ind2 - ind1, ''), substring(acc, ind1 + 1, ind2 - ind1 - 1)
from
rcte
cross apply (select charindex('#', acc) ind1) ca
cross apply (select charindex('#', acc, ind1 + 1) ind2) cb
where
len(acc)>1
) ,cte2 as (
select company, accounts as accounts_raw, Replace( accounts,'..','') as accounts,
LEAD(accounts) OVER(Partition by company ORDER BY accounts) ld,
ROW_NUMBER() OVER(ORDER BY accounts) rn
from rcte
) , cte3 as (
Select company,accounts,ld ,rn
from cte2
WHERE ld not like '%..'
) , cte4 as (
select * from cte3 where accounts not in (select ld from cte3 t1 where t1.rn < cte3.rn)
)
SELECT company,accounts,ld from cte4
UNION
SELECT DISTINCT company,ld,NULL from cte3 where accounts not in (select accounts from cte4 t1)
option (maxrecursion 0)
Result:
It looks like you tagged SSIS so I will provide a solution for that using a script task. All other examples require loading to a staging table.
Use your normal reader (Excel probably) and load
Add a script transformation component
Edit Component
Input Columns - Check both Company and Accounts
Input and Output - Add a new Output and call it CompFirstLast
Add three columns to it - Company string, First int, and Last int
Open Script and paste the following code
public override void Input0_ProcessInputRow(Input0Buffer Row)
{
//Create an array for each group to create rows out of by splitting on '+'
string[] SplitForRows = Row.Accounts.Split('+'); //Note single quotes denoting char
//Deal with each group and create the new Output
for (int i = 0; i < SplitForRows.Length; i++) //Loop each split column
{
CompFirstLastBuffer.AddRow();
CompFirstLastBuffer.Company = Row.Company; //This is static for each incoming row
//Clean up the string getting rid of (). and leaving a delimited list of #
string accts = SplitForRows[i].Replace("(", String.Empty).Replace(")", String.Empty).Replace(".", String.Empty).Substring(1);
//Split into Array
string[] accounts = accts.Split('#');
// Write out first and last and handle null
CompFirstLastBuffer.First = int.Parse(accounts[0]);
if (accounts.Length == 1)
CompFirstLastBuffer.Last_IsNull = true;
else
CompFirstLastBuffer.Last = int.Parse(accounts[1]);
}
}
Make sure you use the right output.

T-SQL join query using distinct values from second table

I know this question might sound like a duplicate, but I've been through every question I could find; though it's still possible it might be a duplicate of a question I might have missed.
I have what at surface value appears to be a trivial requirement but no matter how I script it out there's always some caveat that's just not working. I've tried GROUP, DISTINCT, JOIN, aggregate functions, etc.
Scenario:
PRIMARYTABLE contains a set of campaigns and SECONDARYTABLE contains the dates on which campaigns were run. There can be multiple runs per campaign and I've included a SUBKEY for each run.
Requirement:
I need to be able to get the most recently run campaigns into a list so the user can more easily select from the campaigns that get run the most frequent.
PRIMARYTABLE
KEYCOLUMN INFOCOLUMN
100000 Test 1
100001 Test Campaign
100002 Test Image 2
100003 Test Img
100004 Image Test
100005 Test
100006 Test Image 3
100007 Test Image 4
100008 Test Image 5
100009 Image Comparison Test 2
100010 Testing
100011 Test Fields
100012 Test 5
100013 test
SECONDARYTABLE
KEYCOLUMN SUBKEY DATECOLUMN
100000 100000 2017-06-02 04:09:57.593
100001 100001 2017-06-19 12:09:54.093
100001 100002 2017-06-27 10:51:14.140
100004 100003 2017-06-27 12:33:47.747
100006 100004 2017-06-28 10:29:53.387
100007 100005 2017-06-28 10:36:23.710
100008 100006 2017-06-29 22:31:03.790
100009 100007 2017-06-29 23:07:52.870
100009 100010 2017-10-04 16:05:40.583
100009 100011 2017-10-04 16:09:55.470
100011 100008 2017-09-08 14:02:28.017
100012 100009 2017-09-11 16:17:23.870
100013 100012 2017-11-07 16:55:55.403
100013 100013 2017-11-08 15:37:16.430
Below is somewhat of an idea of more or less what I'm after.
SELECT DISTINCT( a.[INFOCOLUMN] )
FROM [PRIMARYTABLE] a
INNER JOIN [SECONDARYTABLE] b ON ( a.[KEYCOLUMN] = b.[KEYCOLUMN] )
ORDER BY a.[DATECOLUMN]
Here's hoping for a Homer Simpson "Doh!" moment once I see how it's supposed to be done.
Much appreciated.
the most recently run campaigns >> use row_number() over(.. order by ... DESC)
that get run the most frequent >> use count(*) over(partition by ..)
Using window functions row_number() over() and count() over() enables selection by row of data that is "most recent" and ordering by "most frequent". Note that the DESCending order of dates brings about "recent" = 1.
select
p.*, s.*
from PRIMARYTABLE p
inner join (
select KEYCOLUMN, SUBKEY, DATECOLUMN
, row_number() over(partition by KEYCOLUMN order by DATECOLUMN DESC) recent
, count(*) over(partition by KEYCOLUMN) frequency
from SECONDARYTABLE
) s on p.KEYCOLUMN = s.KEYCOLUMN and s.recent = 1
order by s.frequency DESC, p.INFOCOLUMN
You can try this:
DECLARE #PRIMARYTABLE TABLE
(
[KEYCOLUMN] INT
,[INFOCOLUMN] VARCHAR(24)
);
DECLARE #SECONDARYTABLE TABLE
(
[KEYCOLUMN] INT
,[SUBKEY] INT
,[DATECOLUMN] DATETIME2
);
INSERT INTO #PRIMARYTABLE ([KEYCOLUMN], [INFOCOLUMN])
VALUES (100000, 'Test 1')
,(100001, 'Test Campaign')
,(100002, 'Test Image 2')
,(100003, 'Test Img')
,(100004, 'Image Test')
,(100005, 'Test')
,(100006, 'Test Image 3')
,(100007, 'Test Image 4')
,(100008, 'Test Image 5')
,(100009, 'Image Comparison Test 2')
,(100010, 'Testing')
,(100011, 'Test Fields')
,(100012, 'Test 5')
,(100013, 'test');
INSERT INTO #SECONDARYTABLE ([KEYCOLUMN], [SUBKEY], [DATECOLUMN])
VALUES (100000, 100000, '2017-06-02 04:09:57.593')
,(100001, 100001, '2017-06-19 12:09:54.093')
,(100001, 100002, '2017-06-27 10:51:14.140')
,(100004, 100003, '2017-06-27 12:33:47.747')
,(100006, 100004, '2017-06-28 10:29:53.387')
,(100007, 100005, '2017-06-28 10:36:23.710')
,(100008, 100006, '2017-06-29 22:31:03.790')
,(100009, 100007, '2017-06-29 23:07:52.870')
,(100009, 100010, '2017-10-04 16:05:40.583')
,(100009, 100011, '2017-10-04 16:09:55.470')
,(100011, 100008, '2017-09-08 14:02:28.017')
,(100012, 100009, '2017-09-11 16:17:23.870')
,(100013, 100012, '2017-11-07 16:55:55.403')
,(100013, 100013, '2017-11-08 15:37:16.430');
SELECT a.[INFOCOLUMN]
,b.[DATECOLUMN]
FROM #PRIMARYTABLE A
CROSS APPLY
(
SELECT TOP 1 [DATECOLUMN]
FROM #SECONDARYTABLE B
WHERE A.[KEYCOLUMN] = B.[KEYCOLUMN]
ORDER BY [DATECOLUMN] DESC
) b;
It will give you the last execution of each campaign. You can filter then by date or ORDER BY and get TOP N from the final query.
Or you can use ROW_NUMBER:
WITH DataSource AS
(
SELECT A.[INFOCOLUMN]
,B.[DATECOLUMN]
,ROW_NUMBER() OVER (PARTITION BY A.[KEYCOLUMN] ORDER BY B.[KEYCOLUMN]) AS [RowID]
FROM #PRIMARYTABLE A
INNER JOIN #SECONDARYTABLE B
ON A.[KEYCOLUMN] = B.[KEYCOLUMN]
)
SELECT [INFOCOLUMN]
,[DATECOLUMN]
FROM DataSource
WHERE [RowID] = 1;
try this, it will return the list of campaigns in most frequent order of use. Note campaigns never run wont appear in your list. in this case you will to do a left join
SELECT a.[INFOCOLUMN]
FROM [PRIMARYTABLE] a
/* left */ JOIN [SECONDARYTABLE] b ON a.[KEYCOLUMN] = b.[KEYCOLUMN]
group BY a.[infocolumn]
order by max(datecolumn) desc
here is a stub i did to test it
select 10000 id,'Campain A' cname into #a1 union all
select 10002,'Campain B' union all
select 10004,'Campain C' union all
select 10009,'Campain E'
select 10000 id,'20170101' thedate into #a2 union all
select 10000,'20170102' union all
select 10009,'20170103' union all
select 10002,'20170104' union all
select 10004,'20170105' union all
select 10000,'20170201' union all
select 10000,'20170302' union all
select 10009,'20170403' union all
select 10002,'20170104' union all
select 10004,'20170205' union all
select 10000,'20170101' union all
select 10004,'20170302' union all
select 10000,'20170103' union all
select 10002,'20170404' union all
select 10002,'20170105'
select #a1.cname
from #a1 join #a2 on #a1.id = #a2.id
group by #a1.cname
order by max(thedate) desc

Change select with connect by prior from Oracle to SQL Server

Hello I have this part of a view in an Oracle database and I must change it on Microsoft Sql Server.
with V_LOCHIERARHY_N
(nr, nivel, location, parent, systemid, siteid, orgid, count_a, count_wo, children)
AS
SELECT LEVEL, LPAD (' ', 2 * (LEVEL - 1)) || l.LOCATION nivel,
LOCATION, PARENT, systemid, siteid, orgid,
(SELECT COUNT (a.ancestor)
FROM locancestor a
WHERE a.LOCATION = l.LOCATION AND a.siteid = l.siteid),
NVL (COUNT (w.wonum), 0)
FROM maximo.workorder w
WHERE ( w.reportdate >
TO_TIMESTAMP ('2006-06-19 00:00:01',
'YYYY-MM-DD HH24:MI:SS.FF'
)
AND w.istask = 0
AND w.worktype <> 'P'
AND w.LOCATION = l.LOCATION
)
AND w.status <> 'CAN'),
l.children
FROM lochierarchy l
START WITH l.LOCATION = 'StartPoint'
CONNECT BY PRIOR l.LOCATION = l.PARENT AND l.siteid = 'SiteTest'
What I need from this script is to return all the children of a given entry (the description of the children which can be found in locations table).
I have a table with next columns:
Location Parent Systemid Children Siteid Origid Lochierarchyid
A001 StartPoint Primary 2 SiteTest X 106372
A002 A001 Primary 2 SiteTest X 105472
A003 A002 Primary 0 SiteTest X 98654
A004 A002 Primary 1 SiteTest X 875543
A004B A004 Primary 0 SiteTest X 443216
B005 StartPoint Primary 0 SiteTest X 544321
For example for given entry A001 will return
A002
A003
A004
A004B
B005
I have made this view below but I don't know how to integrate it with the first one. Also it doesn't return me the list in the corectly order
Parent
Children 1 of parent
Children a of children 1
children b of children 1
children 2 of parent
children a1 of children 2 and so on.
WITH testCTE AS
(
SELECT l.parent, l.location as child, l.location, l.lochierarchyid
FROM lochierarchy l
where location='SecondLocation' --and siteid='SiteTest'
UNION ALL
SELECT c.Parent, l.parent, l.location, l.lochierarchyid
FROM lochierarchy l
INNER JOIN testCTE c ON l.parent = c.location
)
SELECT *
FROM testCTE c
order BY c.parent,child asc
;
Can please someone help me? :)
Following the query proposed by mathguy, modified for MSSQL (2012)
with
inputs ( location, parent ) as (
select 'A001' , 'StartPoint' union all
select 'A002' , 'A001' union all
select 'A003' , 'A002' union all
select 'A004' , 'A002' union all
select 'A004B', 'A004' union all
select 'B005' , 'StartPoint'
),
r (lvl, location, ord ) as (
select 1, location, CAST(location AS VARCHAR(400))
from inputs
where parent = 'StartPoint'
union all
select r.lvl + 1, i.location, CAST(r.location + '/' + i.location AS VARCHAR(400))
from r join inputs i on r.location = i.parent
)
select REPLICATE(' ', 2 * (lvl-1)) + location as location
from r
order by ord
;
Ouput:
location
-------------------------------------------------------------------
A001
A002
A003
A004
A004B
B005
Here is how you can do this (in Oracle, the only flavor I know) using a recursive query. "The web" reports SQL Server implements recursive queries as well, and with the same syntax (I believe all of this is SQL Standard compliant, so that's not surprising). Give it a try.
Instead of creating a table, I put all the test data in the first CTE. When you try this solution, delete the CTE named inputs first, and use your actual table name in the rest of the query.
with
inputs ( location, parent ) as (
select 'A001' , 'Downstream' from dual union all
select 'A002' , 'A001' from dual union all
select 'A003' , 'A002' from dual union all
select 'A004' , 'A002' from dual union all
select 'A004B', 'A004' from dual union all
select 'B005' , 'Downstream' from dual
),
r ( lvl, location ) as (
select 1, location
from inputs
where parent = 'Downstream'
union all
select r.lvl + 1, i.location
from r join inputs i on r.location = i.parent
)
search depth first by lvl set ord
select lpad(' ', 2 * (lvl-1), ' ') || location as location
from r
order by ord
;
LOCATION
--------------------
A001
A002
A003
A004
A004B
B005
6 rows selected.
ADDED: It seems SQL Server doesn't have the search depth/breadth first clause for recursive CTE's (or perhaps the syntax is different). In any case, here is a primitive "manual" implementation of the same:
with ( ......... ),
r ( lvl, location, ord ) as (
select 1, location, location
from inputs
where parent = 'Downstream'
union all
select r.lvl + 1, i.location, r.location || '/' || i.location
from r join inputs i on r.location = i.parent
)
select lpad(' ', 2 * (lvl-1), ' ') || location as location
from r
order by ord
;

Exact Claim Count for each rows using pivot with join in SQL Server 2012

By executing the below SQL 2012 Query, I got the following output
declare
#ticketstatus nvarchar(20) = 'To Be Allocated'
SELECT m1.ClaimSource, m1.Insurance, n1.[Claim Count], n1.[Claim Value],
ISNULL(m1.[0-30],0) [0-30],
ISNULL(m1.[31-60],0) [31-60],
ISNULL(m1.[61-90],0) [61-90],
ISNULL(m1.[91-120],0) [91-120],
ISNULL(m1.[121-210],0) [121-210],
ISNULL(m1.[210++],0) [210++]
FROM (
SELECT *
FROM (
SELECT ClaimSource, Insurance, CurrentBalance _Count, AgeBucket
FROM ClaimMaster
) m
PIVOT (
COUNT(_Count)
FOR AgeBucket IN ([0-30],[31-60],[61-90],[91-120],[121-210],[210++])
) n
) m1
join
(SELECT Insurance, COUNT(Insurance) [Claim Count], SUM(CurrentBalance) [Claim Value] FROM ClaimMaster
WHERE (TicketStatus = #ticketstatus OR #ticketstatus IS NULL)
GROUP BY Insurance) n1
ON m1.Insurance = n1.Insurance
ORDER BY n1.[Claim Count] DESC
How can I get the correct output for Claim Count, Claim Value on the 4, 5 & 6 rows. Instead of showing full claim count, it should show the respective claim count filter by Claim Source such as Claim Count should be 2 and appropriate Claim Value.
Can anyone help me on this.
Add claimsource and join on that as well?
declare
#ticketstatus nvarchar(20) = 'To Be Allocated'
SELECT m1.ClaimSource, m1.Insurance, n1.[Claim Count], n1.[Claim Value],
ISNULL(m1.[0-30],0) [0-30],
ISNULL(m1.[31-60],0) [31-60],
ISNULL(m1.[61-90],0) [61-90],
ISNULL(m1.[91-120],0) [91-120],
ISNULL(m1.[121-210],0) [121-210],
ISNULL(m1.[210++],0) [210++]
FROM (
SELECT *
FROM (
SELECT ClaimSource, Insurance, CurrentBalance _Count, AgeBucket
FROM ClaimMaster
) m
PIVOT (
COUNT(_Count)
FOR AgeBucket IN ([0-30],[31-60],[61-90],[91-120],[121-210],[210++])
) n
) m1
join
(SELECT ClaimSource, Insurance, COUNT(Insurance) [Claim Count], SUM(CurrentBalance) [Claim Value] FROM ClaimMaster
WHERE (TicketStatus = #ticketstatus OR #ticketstatus IS NULL)
GROUP BY ClaimSource, Insurance) n1
ON m1.Insurance = n1.Insurance and m1.ClaimSource = n1.ClaimSource
ORDER BY n1.[Claim Count] DESC

Resources