June 19, 2019 at 6:14 pm
I have table something like below. Need the table with status1 and status2. How can i achieve that?
June 19, 2019 at 6:27 pm
Please provide sample DDL and INSERT statements for the above structure and you'll have a working solution very quickly.
The absence of evidence is not evidence of absence.
Martin Rees
You can lead a horse to water, but a pencil must be lead.
Stan Laurel
June 19, 2019 at 6:33 pm
CREATE TABLE #LoanStatus
(
LOANNUMBER INT
,CLOSED Varchar(200)
,Pending_Transfer Varchar(200)
,REO Varchar(200)
,Foreclosure Varchar(200)
)
INSERT INTO #LoanStatus ( LOANNUMBER, CLOSED ,Pending_Transfer,REO,Foreclosure ) VALUES (12345,'','Pending_Transfer','','Foreclosure')
INSERT INTO #LoanStatus ( LOANNUMBER, CLOSED ,Pending_Transfer,REO,Foreclosure ) VALUES (12678,'Closed','Pending_Transfer','','')
June 19, 2019 at 6:46 pm
As long as there are always exactly two statuses, this should work:
DROP TABLE IF EXISTS #LoanStatus;
CREATE TABLE #LoanStatus
(
LOANNUMBER INT
,CLOSED VARCHAR(200)
,Pending_Transfer VARCHAR(200)
,REO VARCHAR(200)
,Foreclosure VARCHAR(200)
);
INSERT INTO #LoanStatus
(
LOANNUMBER
,CLOSED
,Pending_Transfer
,REO
,Foreclosure
)
VALUES
(12345, '', 'Pending_Transfer', '', 'Foreclosure')
,(12678, 'Closed', 'Pending_Transfer', '', '');
SELECT *
FROM #LoanStatus ls;
SELECT ls.LOANNUMBER
,Status1 = MAX(COALESCE(
NULLIF(ls.CLOSED, '')
,NULLIF(ls.Pending_Transfer, '')
,NULLIF(ls.REO, '')
,NULLIF(ls.Foreclosure, '')
)
)
,Status2 = MAX(COALESCE(
NULLIF(ls.Foreclosure, '')
,NULLIF(ls.REO, '')
,NULLIF(ls.Pending_Transfer, '')
,NULLIF(ls.CLOSED, '')
)
)
FROM #LoanStatus ls
GROUP BY ls.LOANNUMBER;
The absence of evidence is not evidence of absence.
Martin Rees
You can lead a horse to water, but a pencil must be lead.
Stan Laurel
June 19, 2019 at 8:24 pm
Your code works , if you place the columns as you want to see result ( as example i provided) , but if i place all the columns in same order for the status 1 , statsu2 it does not work.
June 19, 2019 at 8:26 pm
SELECT ls.LOANNUMBER
,Status1 = MAX(COALESCE(
NULLIF(ls.CLOSED, '')
,NULLIF(ls.Pending_Transfer, '')
,NULLIF(ls.REO, '')
,NULLIF(ls.Foreclosure, '')
)
)
,Status2 = MAX(COALESCE(
NULLIF(ls.CLOSED, '')
,NULLIF(ls.Pending_Transfer, '')
,NULLIF(ls.REO, '')
,NULLIF(ls.Foreclosure, '')
)
)
FROM #LoanStatus ls
GROUP BY ls.LOANNUMBER;
June 19, 2019 at 8:40 pm
Your code works , if you place the columns as you want to see result ( as example i provided) , but if i place all the columns in same order for the status 1 , statsu2 it does not work.
Obviously, but what's the problem?
The absence of evidence is not evidence of absence.
Martin Rees
You can lead a horse to water, but a pencil must be lead.
Stan Laurel
June 19, 2019 at 8:44 pm
I just provided two loans but if i take 1000 loans, i do not want same value for status1 , status 2 . instead i want to get different status for each statuses 1 ,2 . So in real world i will not know which field has value and not.
June 19, 2019 at 8:51 pm
Please provide more sample data (as INSERTs) along with desired results for that data, which demonstrates what you are trying to say.
The absence of evidence is not evidence of absence.
Martin Rees
You can lead a horse to water, but a pencil must be lead.
Stan Laurel
June 19, 2019 at 8:56 pm
Your code works , if you place the columns as you want to see result ( as example i provided) , but if i place all the columns in same order for the status 1 , statsu2 it does not work.
That's because the first one is reading the values from left-to-right and the second one is reading the values from right-to-left. This gives you two different values. If you change them both to read left-to-right, you will obviously get the same values for both statuses.
The real problem with Phil's code is that it requires exactly two values for each loan. Of course, you haven't specified what you want to happen when you have more than two values, so I'm willing to overlook this.
Drew
J. Drew Allen
Business Intelligence Analyst
Philadelphia, PA
June 19, 2019 at 9:11 pm
Here is how i am looking for status to be in second table. If there is no entry in table 1 for a loan Then i need status to be 'Active'.
DROP TABLE #Loanstatus
GO
CREATE TABLE #LoanStatus
(
LOANNUMBER INT
,CLOSED Varchar(200)
,Pending_Transfer Varchar(200)
,REO Varchar(200)
,Foreclosure Varchar(200)
,preForeclosure Varchar(200)
)
INSERT INTO #LoanStatus ( LOANNUMBER, CLOSED ,Pending_Transfer,REO,Foreclosure,preForeclosure ) VALUES (12345,'','Pending_Transfer','','Foreclosure','')
GO
INSERT INTO #LoanStatus ( LOANNUMBER, CLOSED ,Pending_Transfer,REO,Foreclosure,preForeclosure ) VALUES (12678,'Closed','Pending_Transfer','','','')
GO
INSERT INTO #LoanStatus ( LOANNUMBER, CLOSED ,Pending_Transfer,REO,Foreclosure,preForeclosure ) VALUES (12567,'','Pending_Transfer','','Foreclosure','')
GO
INSERT INTO #LoanStatus ( LOANNUMBER, CLOSED ,Pending_Transfer,REO,Foreclosure,preForeclosure ) VALUES (12789,'','','','','preForeclosure')
GO
INSERT INTO #LoanStatus ( LOANNUMBER, CLOSED ,Pending_Transfer,REO,Foreclosure,preForeclosure ) VALUES (12978,'CLOSED','Pending_Transfer','REO','','')
Go
INSERT INTO #LoanStatus ( LOANNUMBER, CLOSED ,Pending_Transfer,REO,Foreclosure,preForeclosure ) VALUES (12908,'','','','','')?
June 19, 2019 at 10:18 pm
I just know that Drew is going to post a really snappy solution to this one ... that's what usually happens after I post my overblown version. But here goes ... this works, but I hate cascading CTEs, so would like to see something more elegant.
DROP TABLE IF EXISTS #LoanStatus;
CREATE TABLE #LoanStatus
(
LOANNUMBER INT
,CLOSED VARCHAR(200)
,Pending_Transfer VARCHAR(200)
,REO VARCHAR(200)
,Foreclosure VARCHAR(200)
,preForeclosure VARCHAR(200)
);
INSERT INTO #LoanStatus
(
LOANNUMBER
,CLOSED
,Pending_Transfer
,REO
,Foreclosure
,preForeclosure
)
VALUES
(12345, '', 'Pending_Transfer', '', 'Foreclosure', '')
,(12678, 'Closed', 'Pending_Transfer', '', '', '')
,(12567, '', 'Pending_Transfer', '', 'Foreclosure', '')
,(12789, '', '', '', '', 'preForeclosure')
,(12978, 'CLOSED', 'Pending_Transfer', 'REO', '', '')
,(12908, '', '', '', '', '');
WITH statuses1
AS (SELECT ls.LOANNUMBER
,Status = ls.CLOSED
,rn = 1
FROM #LoanStatus ls
WHERE ls.CLOSED <> ''
UNION ALL
SELECT ls.LOANNUMBER
,ls.Pending_Transfer
,2
FROM #LoanStatus ls
WHERE ls.Pending_Transfer <> ''
UNION ALL
SELECT ls.LOANNUMBER
,ls.REO
,3
FROM #LoanStatus ls
WHERE ls.REO <> ''
UNION ALL
SELECT ls.LOANNUMBER
,ls.Foreclosure
,4
FROM #LoanStatus ls
WHERE ls.Foreclosure <> ''
UNION ALL
SELECT ls.LOANNUMBER
,ls.preForeclosure
,5
FROM #LoanStatus ls
WHERE ls.preForeclosure <> '')
,Statuses2
AS (SELECT statuses1.LOANNUMBER
,Status1 = (CASE
WHEN ROW_NUMBER() OVER (PARTITION BY statuses1.LOANNUMBER
ORDER BY statuses1.LOANNUMBER
,statuses1.rn
) = 1 THEN
statuses1.Status
ELSE
''
END
)
,Status2 = (CASE
WHEN ROW_NUMBER() OVER (PARTITION BY statuses1.LOANNUMBER
ORDER BY statuses1.LOANNUMBER
,statuses1.rn
) = 2 THEN
statuses1.Status
ELSE
''
END
)
,Status3 = (CASE
WHEN ROW_NUMBER() OVER (PARTITION BY statuses1.LOANNUMBER
ORDER BY statuses1.LOANNUMBER
,statuses1.rn
) = 3 THEN
statuses1.Status
ELSE
''
END
)
FROM statuses1)
SELECT Statuses2.LOANNUMBER
,Status1 = MAX(Statuses2.Status1)
,Status2 = MAX(Statuses2.Status2)
,Status3 = MAX(Statuses2.Status3)
FROM Statuses2
GROUP BY Statuses2.LOANNUMBER
UNION ALL
SELECT ls.LOANNUMBER
,Status1 = 'ACTIVE'
,Status2 = ''
,Status3 = ''
FROM #LoanStatus ls
WHERE CONCAT(ls.CLOSED, ls.Foreclosure, ls.Pending_Transfer, ls.preForeclosure, ls.REO) = '';
The absence of evidence is not evidence of absence.
Martin Rees
You can lead a horse to water, but a pencil must be lead.
Stan Laurel
June 19, 2019 at 10:25 pm
I wonder if grouping is even needed. It looks like one row = one loan. Is this true, komal145? Or there are multiple rows with same loan number but different statuses?
--Vadim R.
June 20, 2019 at 2:24 pm
Yes , it is is one row for one loan.
June 20, 2019 at 2:48 pm
I just know that Drew is going to post a really snappy solution to this one ... that's what usually happens after I post my overblown version. But here goes ... this works, but I hate cascading CTEs, so would like to see something more elegant.
Here is the way that I would approach it.
Solution 1 with CROSS APPLY.
WITH CTE AS
(
SELECT LoanNumber, status_desc, ROW_NUMBER() OVER(PARTITION BY LoanNumber ORDER BY status_num) rn
FROM #LoanStatus ls
CROSS APPLY( VALUES(1, Closed), (2, Pending_Transfer), (3, REO), (4, Foreclosure), (5, preForeclosure), (6, 'Active')) st(status_num, status_desc)
WHERE st.status_desc > ''
)
SELECT LoanNumber
,MAX(CASE WHEN rn = 1 THEN status_desc ELSE '' END) AS Status_1
,MAX(CASE WHEN status_desc <> 'Active' AND rn = 2 THEN status_desc ELSE '' END) AS Status_2
,MAX(CASE WHEN status_desc <> 'Active' AND rn = 3 THEN status_desc ELSE '' END) AS Status_3
FROM CTE c
GROUP BY LoanNumber;
Here is another solution that works, but I think the conversion to XML and back may not be performant in the long run.
Solution 2 with XML.
SELECT
ls.LoanNumber
,COALESCE(x.LoanStatuses.value('(/LoanStatuses/LoanStatus)[1]', 'VARCHAR(200)'), '') AS status_1
,COALESCE(x.LoanStatuses.value('(/LoanStatuses/LoanStatus)[2][. != "Active"]', 'VARCHAR(200)'), '') AS status_2
,COALESCE(x.LoanStatuses.value('(/LoanStatuses/LoanStatus)[3][. != "Active"]', 'VARCHAR(200)'), '') AS status_3
FROM #LoanStatus ls
CROSS APPLY
(
SELECT NULLIF(status_desc, '') AS LoanStatus
FROM ( VALUES(1, Closed), (2, Pending_Transfer), (3, REO), (4, Foreclosure), (5, preForeclosure), (6, 'Active')) st(status_num, status_desc)
FOR XML PATH('LoanStatuses'), TYPE
) x(LoanStatuses)
Drew
J. Drew Allen
Business Intelligence Analyst
Philadelphia, PA
Viewing 15 posts - 1 through 15 (of 16 total)
You must be logged in to reply to this topic. Login to reply