Select sub-query using EXEC() to use different database? - sql

It doesn't seem to work when trying to use EXEC() in the SELECT query. Does anyone know of a better way to do this?
The remark comment below "--This work" showed the CASE statement work. But not the "-This doesn't work" part because EXEC() isn't compatible
SELECT
tu.[DisplayCode],
tt.[TenantName],
tt.[EntityType],
tt.[DatabaseName],
tu.[TenantId],
tu.[EmployeeId],
tu.[UserId],
au.[IsAbcoaAdmin],
-- This doesn't work.
CAST(CASE WHEN tu.[EmployeeId] = EXEC('SELECT TOP 1 [EmployeeId] FROM ['+tt.DatabaseName+'].dbo.Employee t1 WHERE t1.[AutoNum] = '+tu.[EmployeeId]+'''') THEN 1 ELSE 0 END AS BIT) AS IsEmployeeExists
-- This work.
--CAST(CASE WHEN tu.[EmployeeId] = (SELECT TOP 1 [EmployeeId] FROM [RodeoNet].dbo.Employee t1 WHERE t1.[AutoNum] = tu.[EmployeeId]) THEN 1 ELSE 0 END AS BIT) AS IsEmployeeExists
FROM [DealPackWebIdentity].[dbo].[ApplicationUser] au
INNER JOIN [DealPackWebIdentity].[dbo].[TenantUser] tu ON au.[Id] = tu.[UserId]
INNER JOIN [DealPackWebIdentity].[dbo].[Tenant] tt ON tu.[TenantId] = tt.[TenantId]
WHERE au.[UserName] = #UserName
AND CAST(CASE WHEN DB_ID(tt.[DatabaseName]) IS NOT NULL THEN 1 ELSE 0 END AS BIT) = 1
AND [IsDisable] = 0
AND tt.[IsActive] = 1
ORDER BY [TenantName], [EntityType]

Related

How to use If Else if and Else in stored procedures | SQL Server

I have created the following stored procedure where user passes input parameters to get the data. The input parameters are optional i.e. passing just one parameter should produce some data.
Here is my code.
ALTER PROC [dbo].[SPR_ECRM_CASE_INFORMATION]
#ID_APPLICATION_NO NVARCHAR(20),
#TX_ID_NO NVARCHAR(20)
AS
BEGIN
SET NOCOUNT ON
IF (#ID_APPLICATION_NO IS NOT NULL ) OR (LEN(#ID_APPLICATION_NO) > 0) AND ((#TX_ID_NO IS NOT NULL) OR (LEN(#TX_ID_NO) > 0))
BEGIN
SELECT DISTINCT
[A].[ID_APPLICATION_NO]
,[A].[TX_APPLICATION_STATUS]
FROM [VW_T_APPLICATION] As [A]
INNER JOIN [CT_L1_APPLICATION_STATUS] [L] ON [L].[TX_L1_APPLICATION_STATUS_CODE] = [A].[TX_APPLICATION_STATUS_CODE]
LEFT JOIN [VW_ST_APPLICATION_APPLICANT] [I] WITH(NOLOCK) ON [I].[ID_APPLICATION_APPLICANT] = (SELECT TOP 1
[II].[ID_APPLICATION_APPLICANT]
FROM
[ST_APPLICATION_APPLICANT] [II] WITH(NOLOCK)
WHERE [II].[ID_APPLICATION_GUID] = [A].[ID_APPLICATION_GUID]
AND [II].[CD_APPLICANT_TYPE] = 81
AND [II].[IN_ACTIVE] = 1
ORDER BY
[II].[ID_APPLICATION_APPLICANT] DESC)
LEFT JOIN [VW_ST_APPLICATION_APPLICANT] [J] WITH(NOLOCK) ON [J].[ID_APPLICATION_APPLICANT] = (SELECT TOP 1
[JJ].[ID_APPLICATION_APPLICANT]
FROM
[ST_APPLICATION_APPLICANT] [JJ] WITH(NOLOCK)
WHERE [JJ].[ID_APPLICATION_GUID] = [A].[ID_APPLICATION_GUID]
AND [JJ].[CD_APPLICANT_TYPE] = 82
AND [JJ].[IN_ACTIVE] = 1
ORDER BY
[JJ].[ID_APPLICATION_APPLICANT] DESC)
WHERE
[I].[TX_ID_NO] = #TX_ID_NO AND [J].[TX_ID_NO] = #TX_ID_NO
AND
[A].[TX_APPLICANT_ID_NO] = #ID_APPLICATION_NO
AND
[A].[IN_ACTIVE] = 1
END
ELSE IF (#ID_APPLICATION_NO IS NOT NULL) OR (LEN(#ID_APPLICATION_NO) > 0)
BEGIN
SELECT DISTINCT
[A].[ID_APPLICATION_NO]
,[A].[TX_APPLICATION_STATUS]
FROM [VW_T_APPLICATION] As [A]
INNER JOIN [CT_L1_APPLICATION_STATUS] [L] ON [L].[TX_L1_APPLICATION_STATUS_CODE] = [A].[TX_APPLICATION_STATUS_CODE]
LEFT JOIN [VW_ST_APPLICATION_APPLICANT] [I] WITH(NOLOCK) ON [I].[ID_APPLICATION_APPLICANT] = (SELECT TOP 1
[II].[ID_APPLICATION_APPLICANT]
FROM
[ST_APPLICATION_APPLICANT] [II] WITH(NOLOCK)
WHERE [II].[ID_APPLICATION_GUID] = [A].[ID_APPLICATION_GUID]
AND [II].[CD_APPLICANT_TYPE] = 81
AND [II].[IN_ACTIVE] = 1
ORDER BY
[II].[ID_APPLICATION_APPLICANT] DESC)
LEFT JOIN [VW_ST_APPLICATION_APPLICANT] [J] WITH(NOLOCK) ON [J].[ID_APPLICATION_APPLICANT] = (SELECT TOP 1
[JJ].[ID_APPLICATION_APPLICANT]
FROM
[ST_APPLICATION_APPLICANT] [JJ] WITH(NOLOCK)
WHERE [JJ].[ID_APPLICATION_GUID] = [A].[ID_APPLICATION_GUID]
AND [JJ].[CD_APPLICANT_TYPE] = 82
AND [JJ].[IN_ACTIVE] = 1
ORDER BY
[JJ].[ID_APPLICATION_APPLICANT] DESC)
WHERE
[A].[TX_APPLICANT_ID_NO] = #ID_APPLICATION_NO
AND
[A].[IN_ACTIVE] = 1
END
ELSE IF (#TX_ID_NO IS NOT NULL) OR (LEN(#TX_ID_NO) > 0)
BEGIN
SELECT DISTINCT
[A].[ID_APPLICATION_NO]
,[A].[TX_APPLICATION_STATUS]
FROM [VW_T_APPLICATION] As [A]
INNER JOIN [CT_L1_APPLICATION_STATUS] [L] ON [L].[TX_L1_APPLICATION_STATUS_CODE] = [A].[TX_APPLICATION_STATUS_CODE]
LEFT JOIN [VW_ST_APPLICATION_APPLICANT] [I] WITH(NOLOCK) ON [I].[ID_APPLICATION_APPLICANT] = (SELECT TOP 1
[II].[ID_APPLICATION_APPLICANT]
FROM
[ST_APPLICATION_APPLICANT] [II] WITH(NOLOCK)
WHERE [II].[ID_APPLICATION_GUID] = [A].[ID_APPLICATION_GUID]
AND [II].[CD_APPLICANT_TYPE] = 81
AND [II].[IN_ACTIVE] = 1
ORDER BY
[II].[ID_APPLICATION_APPLICANT] DESC)
LEFT JOIN [VW_ST_APPLICATION_APPLICANT] [J] WITH(NOLOCK) ON [J].[ID_APPLICATION_APPLICANT] = (SELECT TOP 1
[JJ].[ID_APPLICATION_APPLICANT]
FROM
[ST_APPLICATION_APPLICANT] [JJ] WITH(NOLOCK)
WHERE [JJ].[ID_APPLICATION_GUID] = [A].[ID_APPLICATION_GUID]
AND [JJ].[CD_APPLICANT_TYPE] = 82
AND [JJ].[IN_ACTIVE] = 1
ORDER BY
[JJ].[ID_APPLICATION_APPLICANT] DESC)
WHERE
[I].[TX_ID_NO] = #TX_ID_NO OR [J].[TX_ID_NO] = #TX_ID_NO
AND
[A].[IN_ACTIVE] = 1
END
ELSE
BEGIN
RETURN NULL
END
END
I have used if else if and else condition but it fails to return the data.
DECLARE #A NVARCHAR(30)
DECLARE #B NVARCHAR(20)
SET #A = 'C192'
SET #B = 'ABC'
EXEC SPR_ECRM_CASE_INFORMATION #A, ''
EXEC SPR_ECRM_CASE_INFORMATION '', #B
EXEC SPR_ECRM_CASE_INFORMATION '', ''
Firstly, the else if condition fails and my code here is redundant. Is there any better way to optimize this. Your help is appreciated.
If you want to optimize for performance, you can create a single procedure for each query. Each will get it's own query plan. You can call each in this procedure.
Looking at each query, I see the sub-query in the ON clause. I also see NOLOCK which I normally consider a bad sign. Also see the DISTINCT. These are all clues that the query can be simplified. SQL Server will then be more likely to optimize the query. (You can ask for the same thing in more than one way. The more complex the logic, the less likely SQL will find the best plan.)
If the data in [VW_T_APPLICATION] is already distinct, then get rid of DISTINCT and use EXISTS instead of LEFT JOINS - one EXISTS for 81 and one for 82. (I'm assuming you are not going to need columns from these.)
The use of "VW" implies the use of views. The view can hide a lot of logic that gets in the way of a simple query.
Is this part (your first IF) correct in terms of bracketing? It will run if #ID_Application_No is NOT NULL, regardless of whether #TX_ID_No has a value.
IF (#ID_APPLICATION_NO IS NOT NULL ) OR (LEN(#ID_APPLICATION_NO) > 0) AND ((#TX_ID_NO IS NOT NULL) OR (LEN(#TX_ID_NO) > 0))
I'm guessing you want either
a) brackets around the ID_Application_No part e.g.,
IF ((#ID_APPLICATION_NO IS NOT NULL ) OR (LEN(#ID_APPLICATION_NO) > 0)) AND ((#TX_ID_NO IS NOT NULL) OR (LEN(#TX_ID_NO) > 0))
or b) want it to be an AND (this is my most likely guess) e.g.,
IF (#ID_APPLICATION_NO IS NOT NULL ) AND (LEN(#ID_APPLICATION_NO) > 0) AND ((#TX_ID_NO IS NOT NULL) OR (LEN(#TX_ID_NO) > 0))
Note you can simplify some things e.g., when you have IF (#ID_APPLICATION_NO IS NOT NULL) OR (LEN(#ID_APPLICATION_NO) > 0), the first part will always be true if the second part is true. In those cases, you can use only IF (#ID_APPLICATION_NO IS NOT NULL) and it will give the same results.

Cannot use an aggregate or a subquery

I'm trying to group this case expression but unfortunately I'm getting an error.
select da.order_id, osl.itemid, sum(case when osl.sku = '00005' then 0 when osl.sku = '00006' then 0 else osl.price * sil.quantity end) merchcost, sum(sil.merchUnitCost * sil.quantity) cogs, sum(sil.quantity) quantity,
CASE
WHEN EXISTS (SELECT * FROM fcat.dbo.subscriptionskus a where a.itemId = osl.itemid) then 1
WHEN EXISTS (SELECT * FROM foam.dbo.subscriptionprogram b where b.orderStateLineId = osl.orderStateLine_id ) then 1
else 0
END as isAdmin,
CASE
WHEN EXISTS (SELECT * FROM fcat.dbo.subscriptionskus a where a.itemId = osl.itemid) then CAST('subscriptionskus' as varchar(MAX))
WHEN EXISTS (SELECT * FROM foam.dbo.subscriptionprogram b where b.orderStateLineId = osl.orderStateLine_id ) then CAST('subscriptionprogram' as varchar(MAX))
else 'NotListed'
END as SubTable
from #dispatchAmounts da
inner join orderstates os on os.order_id = da.order_id
inner join orderstatelines osl on osl.orderState_id = os.orderState_id
inner join shippingIntentLines sil on sil.orderStateLine_id = osl.orderStateLine_id and da.shippingIntent_nbr = sil.shippingIntent_nbr
where da.code = 'merch' and sil.quantity > 0
group by da.order_id, osl.itemid, CASE
WHEN EXISTS (SELECT * FROM fcat.dbo.subscriptionskus a where a.itemId = osl.itemid) then 1
WHEN EXISTS (SELECT * FROM foam.dbo.subscriptionprogram b where b.orderStateLineId = osl.orderStateLine_id ) then 1
else 0
END,CASE
WHEN EXISTS (SELECT * FROM fcat.dbo.subscriptionskus a where a.itemId = osl.itemid) then CAST('subscriptionskus' as varchar(MAX))
WHEN EXISTS (SELECT * FROM foam.dbo.subscriptionprogram b where b.orderStateLineId = osl.orderStateLine_id ) then CAST('subscriptionprogram' as varchar(MAX))
else 'NotListed'
END
ERROR:
Cannot use an aggregate or a subquery in an expression used for the group by list of a GROUP BY clause.
Is there anyway I can make this work?
I have a couple of suggestions. You are using select * in your case statements , but the columns referenced by '*' are not in your group by clause. To add them would be a bad way to fix the problem. Instead use ' select 1 ' and see what happens.
Second recommendation is to just not use the when exists rather use left join using sub queries and use those in your case statements.
So what I did is.
1. Removed the Case Statement on the Group By.
2. Modified the SubQueries on the Case Statement. Followed #Shiv Sidhu recommendation.
Thanks for everyone.

UPDATE using case when exists ( don't get the right result)

i'm trying to update a table that is alimented by 2 flows, the 1st one i have to make FillRateCode (the column i want to update) equal to FillRateCode from BWH_OTC_Order but for the 2nd flow i put it equal to '-1'
this is my script:
use BITS
;with tmp as (
select SalesOrderItemNum, SalesOrderNum, FillRateCode
From
BWH_OTC_Order
INNER JOIN REF_Company Comp
ON (Comp.CompanyCode= BWH_OTC_Order.CompanyCode AND Comp.DivisionCode='TEE')
where RevisedPGIDate is not null
)
UPDATE bits_tee.dbo.DMT_TEE_OTC_OrderFulFill
SET FillRateCode = case when exists ( select 1 from tmp) then tmp.FillRateCode else '-1' end
FROM bits_tee.dbo.DMT_TEE_OTC_OrderFulFill DMT
left outer join tmp
on tmp.SalesOrderItemNum = DMT.SalesOrderItemNum
and tmp.SalesOrderNum = DMT.SalesOrderNum
and this is the result i get
NB BWH_FillRateCode DMT_FillRateCode
124457 NULL NULL
73991 0 0
457507 1 1
28632 -1 -1
4849 2 2
34262 3 3
for nulls the correct resault is to get '-1' in DMT_FillRateCode
any issues?
Thx by advence
You can use ISNULL or COALESCE to replace NULL with something else. Your exists( select 1 from tmp) is pointless since it only checks if there are any rows (so not only related rows).
WITH tmp
AS (SELECT SalesOrderItemNum,
SalesOrderNum,
FillRateCode
FROM BWH_OTC_Order
INNER JOIN REF_Company Comp
ON ( Comp.CompanyCode = BWH_OTC_Order.CompanyCode
AND Comp.DivisionCode = 'TEE' )
WHERE RevisedPGIDate IS NOT NULL)
UPDATE DMT
SET DMT.FillRateCode = ISNULL(tmp.FillRateCode, '-1')
FROM bits_tee.dbo.DMT_TEE_OTC_OrderFulFill DMT
LEFT OUTER JOIN tmp
ON tmp.SalesOrderItemNum = DMT.SalesOrderItemNum
AND tmp.SalesOrderNum = DMT.SalesOrderNum
Maybe I'm misinterpreting your question, but if you just want to replace null values with -1 you can use the isnull function
isnull(tmp.FillRateCode,-1) -- I'm guessing the -1 is an int, and not a char '-1'
instead of
case when exists ( select 1 from tmp) then tmp.FillRateCode else '-1' end

SQL Case statement how to get value regardless of other results

Here is my statement:
SELECT
CASE
WHEN #UserRole = 1 THEN 1
ELSE 0
END AS [CanEdit],
F.FundingStreamName
FROM FundingStream AS F
LEFT JOIN Projects AS P ON P.FundingStream = F.FundingStreamID
WHERE ProjectNumber = #ProjectNumber
I noticed if FundingStreamID is null, the case statement will return nothing as well, how can I get the case statement to execute regardless if there is a funding stream or not? Thanks.
I think the problem is that your where clause is "undoing" your left outer join. Try moving the condition to the on clause:
SELECT (CASE WHEN #UserRole = 1 THEN 1
ELSE 0
END) AS [CanEdit],
F.FundingStreamName
FROM FundingStream F LEFT JOIN
Projects P
ON P.FundingStream = F.FundingStreamID AND
P.ProjectNumber = #ProjectNumber ;
Using #MicSim answer:
SELECT
CASE
WHEN #UserRole = 1 THEN 1
ELSE 0
END AS [CanEdit],
F.FundingStreamName
FROM FundingStream AS F
RIGHT JOIN Projects AS P ON P.FundingStream = F.FundingStreamID
WHERE ProjectNumber = #ProjectNumber
Thanks again for the help!

TSQL - TOP and COUNT in one SELECT

i try to combine these two statements to one, but all my tries failed!
Is it possible to merge them?
-- Is there a open answer?
SELECT CASE COUNT(tbl_Communication.pk_Communication) WHEN 0
THEN 0 ELSE 1 END AS hasAnsweredCom
FROM tbl_Communication
JOIN tbl_CommunicationElements ON tbl_CommunicationElements.pk_Communication = tbl_Communication.pk_Communication
WHERE tbl_Communication.pk_Ticket = #pk_Ticket
AND tbl_Communication.isClosed = 0
AND tbl_Communication.pk_CommunicationType = (SELECT pk_CommunicationType
FROM tbl_CommunicationType
WHERE name = 'query')
-- Get the answer text
SELECT TOP 1 tbl_Communication.subject AS hasAnsweredComStepName
FROM tbl_Communication
JOIN tbl_CommunicationElements ON tbl_CommunicationElements.pk_Communication = tbl_Communication.pk_Communication
WHERE tbl_Communication.pk_Ticket = #pk_Ticket
AND tbl_Communication.isClosed = 0
AND tbl_Communication.pk_CommunicationType = (SELECT pk_CommunicationType
FROM tbl_CommunicationType
WHERE name = 'query')
ORDER BY tbl_Communication.pk_Communication
Right join trick.
SELECT TOP 1
CASE WHEN tbl_CommunicationElements.pk_Communication IS NULL THEN 0 ELSE 1 END hasAnsweredCom
, tbl_Communication.subject AS hasAnsweredComStepName
FROM tbl_Communication
JOIN tbl_CommunicationElements ON tbl_CommunicationElements.pk_Communication = tbl_Communication.pk_Communication
RIGHT JOIN (VALUES(1)) AS Ext(x) ON (
tbl_Communication.pk_Ticket = #pk_Ticket
AND tbl_Communication.isClosed = 0
AND tbl_Communication.pk_CommunicationType = (SELECT pk_CommunicationType
FROM tbl_CommunicationType
WHERE name = 'query')
)
If you are willing to put the two results on one line, the following works:
select (CASE count(*) WHEN 0 THEN 0 ELSE 1 END) AS hasAnsweredCom,
MAX(case when seqnum = 1 then subject end) as hasAnsweredComStepName
from (SELECT tbl_Communication.pk_Communication, tbl_Communication.subject,
ROW_NUMBER() over (order by pk_communication) as seqnum
FROM tbl_Communication
JOIN tbl_CommunicationElements ON tbl_CommunicationElements.pk_Communication = tbl_Communication.pk_Communication
WHERE tbl_Communication.pk_Ticket = #pk_Ticket
AND tbl_Communication.isClosed = 0
AND tbl_Communication.pk_CommunicationType = (SELECT pk_CommunicationType
FROM tbl_CommunicationType
WHERE name = 'query')
) t
The second value will be NULL if there are no answers.
As for returning two rows. My guess is that subject is a string whereas hasAnsweredCom is an integer. The types conflict, so any sort of union or bringing the results together will probably result in a type conflict on the second row.