Creating a view in SQL with a case statement in the select - sql

I know something must be wrong with my syntax but I can't seem to figure it out.
I want to populate this column prop_and_cas_dtl_prdct_desc from either expir_prop_and_cas_dtl_prdct_cd or ren_prop_and_cas_dtl_prdct_cd depending on the value in type_indicator but before it goes into prop_and_cas_dtl_prdct_desc it should look up the prop_and_cas_dtl_prdct_desc from pc_ref_detail_product_cd and select the one corresponding to its expir_prop_and_cas_dtl_prdct_cd or ren_prop_and_cas_dtl_prdct_cd.
I apologize for the terrible indenting, I know it is difficult to read but this is the best way I know how to put it.
select
,ren_prop_and_cas_dtl_prdct_cd
...
,p_and_c_cd
,case when type_indicator in ('R','C') then
select prop_and_cas_dtl_prdct_desc
from pc_ref_detail_product_cd a inner join op_pif_coverage_rpc_new b
on a.prop_and_cas_dtl_prdct_cd = b.expir_prop_and_cas_dtl_prdct_cd
else when type_indicator in ('N','O') then
select prop_and_cas_dtl_prdct_desc
from pc_ref_detail_product_cd a inner join op_pif_coverage_rpc_new b
on a.prop_and_cas_dtl_prdct_cd = b.ren_prop_and_cas_dtl_prdct_cd
else NULL
END
AS prop_and_cas_dtl_prdct_desc
FROM dbo.op_pif_coverage_rpc_new
Here is the code I used to create my reference table
create table pc_ref_detail_product_cd(
prop_and_cas_dtl_prdct_cd char(2),
prop_and_cas_dtl_prdct_desc char(30)
)
insert into pc_ref_detail_product_cd (prop_and_cas_dtl_prdct_cd, prop_and_cas_dtl_prdct_desc)
values ('01', 'CORE'),
('02', 'FORECLOSED'),
('04', 'TRUST'),
('06', 'MORTGAGE HOLDERS E&O'),
('07', 'SECURITY INTEREST E&O')

If you need to select column from different table depending on value in additional column you need to include all tables in query, with appropriate JOIN and than use case statement like so
SELECT CASE WHEN a.MyColumn = 0 THEN b.SomeColumn
WHEN a.MyColumn = 1 THEN a.SomeColumn
END AS SomeColumn
FROM MyTableA AS a
JOIN MyTableB AS b
ON a.ID = b.ID
Instead of select statement in case statement, you just going to select column from ether table that you need for each particular case.

I got it figured out. Here is the SQL I used. Sorry if it wasn't apparent what I wanted to do from my horrible code in the original question.
select
,ren_prop_and_cas_dtl_prdct_cd
...
,p_and_c_cd
,case when type_indicator in ('R','C') then
(select prop_and_cas_dtl_prdct_desc
from pc_ref_detail_product_cd a where expir_prop_and_cas_dtl_prdct_cd = prop_and_cas_dtl_prdct_cd)
when type_indicator in ('N','O') then
(select prop_and_cas_dtl_prdct_desc
prop_and_cas_dtl_prdct_desc
from pc_ref_detail_product_cd a where ren_prop_and_cas_dtl_prdct_cd = prop_and_cas_dtl_prdct_cd)
else NULL
END
AS prop_and_cas_dtl_prdct_desc
FROM dbo.op_pif_coverage_rpc_new

Related

Combining INSERT and CASE SQL Server Queries

Here are a couple of SQL queries that I am trying to either write as a single query or two queries. I have tried various possibilities that I could think of but non worked.
I have a blank table tbl_Z. I am trying to LEFT JOIN tbl_A and tbl_B and load the result into tbl_Z plus update the Status column in tbl_Z from tbl_A based on criteria in the 2 SQL statements shown here:
INSERT INTO tbl_Z
SELECT a.*
FROM tbl_A a
LEFT JOIN tbl_B b ON a.AccountNumber = b.AccountNumber
WHERE a.Period = '09/30/2021'
AND b.AccountNumber IS NULL
UPDATE Z
SET Status = (SELECT
f.ContractDate, f.BK_Date, f.Period,
CASE
WHEN ISNULL(f.ContractDate, '1/1/1900') < ISNULL(f.BK_Date, '1/1/1900') AND f.BK_Date < ISNULL(f.Period, '1/1/1900')
THEN 'Bankrupt.Attrit'
ELSE 'Attrit'
END AS Status
FROM
tbl_A f
WHERE
Period = '09/30/2021')
Any help will be greatly appreciated.
I don't know about fields name, just add fields name in select put the case statement in write order of fields.
INSERT INTO tbl_Z
SELECT -- please write your all tbl_A fields here and then place below case in write order of selection
,
CASE
WHEN ISNULL(f.ContractDate, '1/1/1900') < ISNULL(f.BK_Date, '1/1/1900')
AND f.BK_Date < ISNULL(f.Period, '1/1/1900')
THEN 'Bankrupt.Attrit'
ELSE 'Attrit'
END AS Status
FROM tbl_A a
LEFT JOIN tbl_B b ON a.AccountNumber = b.AccountNumber
WHERE a.Period = '09/30/2021'
AND b.AccountNumber IS NULL;

Change existing sql to left join only on first match

Adding back some original info for historical purposes as I thought simplifying would help but it didn't. We have this stored procedure, in this part it is selecting records from table A (calldetail_reporting_agents) and doing a left join on table B (Intx_Participant). Apparently there are duplicate rows in table B being pulled that we DON'T want. Is there any easy way to change this up to only pick the first match on table B? Or will I need to rewrite the whole thing?
SELECT 'Agent Calls' AS CallType,
CallDate,
CallTime,
RemoteNumber,
DialedNumber,
RemoteName,
LocalUserId,
CallDurationSeconds,
Answered,
AnswerSpeed,
InvalidCall,
Intx_Participant.Duration
FROM calldetail_reporting_agents
LEFT JOIN Intx_Participant ON calldetail_reporting_agents.CallID = Intx_Participant.CallIDKey
WHERE DialedNumber IN ( SELECT DialedNumber
FROM #DialedNumbers )
AND ConnectedDate BETWEEN #LocStartDate AND #LocEndDate
AND (#LocQueue IS NULL OR AssignedWorkGroup = #LocQueue)
Simpler version: how to change below to select only first matching row from table B:
SELECT columnA, columnB FROM TableA LEFT JOIN TableB ON someColumn
I changed to this per the first answer and all data seems to look exactly as expected now. Thank you to everyone for the quick and attentive help.
SELECT 'Agent Calls' AS CallType,
CallDate,
CallTime,
RemoteNumber,
DialedNumber,
RemoteName,
LocalUserId,
CallDurationSeconds,
Answered,
AnswerSpeed,
InvalidCall,
Intx_Participant.Duration
FROM calldetail_reporting_agents
OUTER APPLY (SELECT TOP 1
*
FROM Intx_Participant ip
WHERE calldetail_reporting_agents.CallID = ip.CallIDKey
AND calldetail_reporting_agents.RemoteNumber = ip.ConnValue
AND ip.HowEnded = '9'
AND ip.Recorded = '0'
AND ip.Duration > 0
AND ip.Role = '1') Intx_Participant
WHERE DialedNumber IN ( SELECT DialedNumber
FROM #DialedNumbers )
AND ConnectedDate BETWEEN #LocStartDate AND #LocEndDate
AND (#LocQueue IS NULL OR AssignedWorkGroup = #LocQueue)
You can try to OUTER APPLY a subquery getting only one matching row.
...
FROM calldetail_reporting_agents
OUTER APPLY (SELECT TOP 1
*
FROM intx_Participant ip
WHERE ip.callidkey = calldetail_reporting_agents.callid) intx_participant
WHERE ...
You should add an ORDER BY in the subquery. Otherwise it isn't deterministic which row is taken as the first. Or maybe that's not an issue.

SQL Filling In Values From A Second Table

I came up with this query to fill in a missing field from a second table using a subquery.
I can not modify the original table
SELECT
CASE WHEN original.target_field IS NULL THEN
(SELECT fill_in.target_field FROM second.table fill_in
WHERE original.id = fill_in.id)
ELSE
original.target_field END AS myField
FROM
primary.table original
I was wondering if I was missing something and if there was a more performant way to do this?
You could use LEFT JOIN and COALESCE instead of correlated subquery:
SELECT COALESCE(original.target_field,fill_in.target_field) AS myField
FROM primary.table original
LEFT JOIN second.table fill_in
ON original.id = fill_in.id
It is always worth testing different methods. But your query should be fine with an appropriate index.
I would write it as:
SELECT (CASE WHEN o.target_field IS NULL
THEN (SELECT f.target_field
FROM second.table f
WHERE o.id = f.id
)
ELSE o.target_field
END) AS myField
FROM primary.table o;
You want an index on second.table(id, target_field). You would want the same index for the LEFT JOIN version.

Using UNION in SQL with queries and subqueries

I am using the following code to try to UNION two sets of data, although it runs without error, it is running for over 10 minutes and not returning results so Im wondering if there is something Ive done wrong?
select BIH.SourceCode, BIH.MarketValueAmt as CorrectedAmt
from [dbo].[IRA_HIST] as BIH
JOIN
(select accountno, accountclass
from accounttable
where accountclass in ('A','B','C','D')) AS AccountNos
ON BIH.ACCOUNTNO = ACCOUNTNOS.ACCOUNTNO
where BIH.securityno > '0'
UNION
SELECT SourceCode, (Amount*(-1)) as CorrectedAmt
from accttable a, activitytable b
where a.accountclass in ('A','B','C','D')
and b.recordtype in ('r','c')
Any guidance is so helpful.
Since there are no other computations and transformations needed in data from accounttable, you can directly join it with ira_hist and no need to have the sub-query. Also, you need to have this ON a.[key column] = b.[key column] -- probably accountno on your join in your second query
SELECT BIH.SourceCode,
BIH.MarketValueAmt AS CorrectedAmt
FROM [dbo].[IRA_HIST] BIH
JOIN accounttable AccountNos
ON BIH.ACCOUNTNO = ACCOUNTNOS.ACCOUNTNO
AND BIH.securityno > '0'
AND AccountNos.accountclass in ('A','B','C','D')
UNION -- or UNION ALL if you want to retain duplicates
SELECT SourceCode,
(Amount*(-1)) as CorrectedAmt
FROM accttable a,
JOIN activitytable b
ON a.[key column] = b.[key column] -- probably accountno
AND a.accountclass IN ('A','B','C','D')
AND b.recordtype IN ('r','c')
In your 2nd SELECT, since you are querying the same table twice, you should be able to JOIN on a common key (e.g. FROM TABLE a JOIN TABLE b ON a.cKey = b.cKey).
Or, you could simplify that 2nd SELECT:
FROM TABLE WHERE AccountClass IN ('A', 'B',...) OR RecordType IN ('r', 'c')

Assign a value to a variable in a select statement and then used to find value in nested select statement

I'm getting the error
A SELECT statement that assigns a value to a variable must not be combined with data-retrieval operations.
Here's my SELECT statement.
SELECT A.vendor_id, **#vendor_employee** = A.vendor_employee_id
, B.txt_first_name, B.txt_last_name,
SELECT txt_Vendor_Employee_Detail_Element,
(CASE
WHEN txt_Vendor_Employee_Detail_Value <> ''
AND txt_Vendor_Employee_Detail_Value IS NOT NULL
THEN txt_Vendor_Employee_Detail_Value
ELSE CONVERT(VARCHAR, txt_Vendor_Employee_Detail_Date)
END) AS Vendor_Detail_Element_Value
FROM t_vendor_employee_detail
WHERE vendor_employee_id = **#vendor_employee**)
FROM...
Yes, basically you can't return data and assign variables in the same select statement. What I think you intend to do is a correlated subquery which references an outer value.
That wolud look something like this:
SELECT A.vendor_id, A.vendor_employee_id
, B.txt_first_name, B.txt_last_name,
(SELECT d.txt_Vendor_Employee_Detail_Element
FROM t_vendor_employee_detail d
WHERE d.vendor_employee_id = A.Vendor_employee_id /* references outside the subqquery */)
FROM...
but you are also returning multiple rows in your subquery which should probably be rewritten as a join.
SELECT A.vendor_id, A.vendor_employee_id
, B.txt_first_name, B.txt_last_name,
d.txt_Vendor_Employee_Detail_Element,
(CASE
WHEN D.txt_Vendor_Employee_Detail_Value <> ''
AND d.txt_Vendor_Employee_Detail_Value IS NOT NULL
THEN d.txt_Vendor_Employee_Detail_Value
ELSE CONVERT(VARCHAR, d.txt_Vendor_Employee_Detail_Date)
END) AS Vendor_Detail_Element_Value
FROM vendor_table_A A
INNER JOIN t_vendor_employee_detail d
ON d.vendor_employee_id = A.vendor_employee_id
INNER JOIN vendor_table_B B
ON...
These examples will give you the basic idea but we would really need the whole query to give you a complete solution.
This looks like something that could be rewritten using a JOIN. It's hard to say how without seeing the whole query, but here is an attempt:
SELECT A.vendor_id, A.vendor_employee_id
, B.txt_first_name, B.txt_last_name,
c.txt_Vendor_Employee_Detail_Element,
(CASE
WHEN c.txt_Vendor_Employee_Detail_Value <> ''
AND c.txt_Vendor_Employee_Detail_Value IS NOT NULL
THEN c.txt_Vendor_Employee_Detail_Value
ELSE CONVERT(VARCHAR, c.txt_Vendor_Employee_Detail_Date)
END) AS Vendor_Detail_Element_Value
FROM ...
INNER JOIN t_vendor_employee_detail c
ON c.vendor_employee_id = A.vendor_employee_id
As the error message says, you cannot use a variable in the way you are trying.
You can retrieve and assign data altogether using a merge statement.
Something like this:
DECLARE #ID TABLE (
ID INT
)
MERGE INTO #ID
USING (
select 1 a,2 b,3 c
) as src
ON ( 1 = 2 )
WHEN NOT MATCHED THEN
INSERT (ID)
VALUES (Src.a)
OUTPUT src.b, src.c
;
SELECT * FROM #ID