I am using the following query:
if(#usertype = 'all')
begin
select *
from tbllogin a
left join tblUserType_Master b on a.typeid = b.id
where (b.user_type = 'agent' or b.user_type = 'branch') ;
end
else if(#usertype = 'branch')
begin
select *
from tbllogin a
left join tblUserType_Master b on a.typeid = b.id
where b.user_type = 'branch' ;
end
else if(#usertype = 'agent')
begin
select *
from tbllogin a
left join tblUserType_Master b on a.typeid = b.id
where b.user_type = 'agent' ;
end
This works perfectly fine but the only difference between the three queries is the where condition. Is there any way that I can store the value of where condition in a variable and just add it to the common part.
You already have a variable with the value as far as I can see. Why not simply use it:
select
*
from
tbllogin a
left join tblUserType_Master b on a.typeid=b.id
where
b.user_type = #usertype or (#usertype='all' and b.usertype in ('branch','agent'))
I would also like to point out a couple of things: you are using left joins but comparing to the right-side table, which will eliminate all records from the tbllogin that do not have a match in the tblUserType_Master anyway.
You can do the following instead, it will surely perform better:
select
*
from
tbllogin a
inner join tblUserType_Master b on a.typeid=b.id
where
b.user_type = #usertype or (#usertype='all' and b.usertype in ('branch','agent'))
Also, I strongly recommend against using select *, listing the columns explicitly is a recommended path.
Use CASE Statement in WHERE Clause to get your result :
SELECT * FROM tbllogin a
LEFT OUTER JOIN tblUserType_Master b ON a.typeid=b.id
WHERE ( #usertype='all' AND b.user_type IN ('agent','branch') ) OR
b.user_type = CASE WHEN #usertype='branch' THEN 'branch'
WHEN #usertype='agent' THEN 'agent' END
Related
In this stored procedure, I need to pass multiple parameter values in #GDNNO. Right now I can pass only a single value.
Please help me.
ALTER PROCEDURE dbo.xspSHEGONPrintQuery4
#GDNNO varchar(4000) = ''
AS
BEGIN
SELECT
a.ID, a.[To], a.FlowCode, a.TranNum, a.Status,
ART.ARTICLECODE, StockGDNID, DetailID, SubDocCode, ArticleID,
ColorCode, ColorName, SizeCode, SizeName,
DispatchedUnits * (CASE WHEN u.value IS NULL THEN FreezeStoringUOM ELSE u.value END) AS DispatchedUnits
FROM
xtstockgdn a (nolock)
JOIN
xtstockgdndetail b (nolock) ON a.id = b.stockgdnid
JOIN
XTARTICLE ART (nolock) ON ART.ID = B.ARTICLEID
LEFT JOIN
xtUOMConversion u (nolock) ON u.FromUOM = art.StoringUOM
AND u.ToUOM = art.consuom
WHERE
a.ID IN (#GDNNO)
AND FlowCode = 'POO_RET[E-]'
END
Since your query is only Select it can be change to TVF(table-value function). Change your Procedure to TVF
CREATE FUNCTION dbo.xspSHEGONPrintQuery4(
#GDNNO varchar(4000) = ''
)
RETURNS TABLE
AS
RETURN
SELECT
a.ID, a.[To], a.FlowCode, a.TranNum, a.Status,
ART.ARTICLECODE, StockGDNID, DetailID, SubDocCode, ArticleID,
ColorCode, ColorName, SizeCode, SizeName,
DispatchedUnits * (CASE WHEN u.value IS NULL THEN FreezeStoringUOM ELSE u.value END) AS DispatchedUnits
FROM
xtstockgdn a (nolock)
JOIN
xtstockgdndetail b (nolock) ON a.id = b.stockgdnid
JOIN
XTARTICLE ART (nolock) ON ART.ID = B.ARTICLEID
LEFT JOIN
xtUOMConversion u (nolock) ON u.FromUOM = art.StoringUOM
AND u.ToUOM = art.consuom
WHERE
a.ID IN (#GDNNO)
AND FlowCode = 'POO_RET[E-]'
END
Then use Cross apply to your TVF
Select a.GDNNO,b.* from yourtable a /*list of GDNNO Values */
Cross Apply dbo.xspSHEGONPrintQuery4(a.GDNNO) b
you can use Dynamic query as well
i have query below
SELECT #RoleUser = MR.Code FROM MasterRole MR INNER JOIN MasterUsersRole MUR ON MR.Id = MUR.RoleId
INNER JOIN MasterUsers MU ON Mu.UserCode = MUR.UserCode
WHERE MU.UserCode = #UserLoginID
select 1 Num
, MyHistory.ID
, MyHistory.RequestNumber
, MyHistory.FlowID
, MyHistory.FlowProcessStatusID
from
(
select *
from Requests R
inner join
(
--DECLARE #UserLoginID nvarchar(200) = 'dum.testing.3'
select distinct
RequestID
from dbo.RequestTrackingHistory RTH
where IIF(#UserLoginID = 'admin', #UserLoginID, RTH.CreatedBy) = #UserLoginID
OR ( CreatedBy IN
SELECT Mu.UserCode from MasterUsers MU
INNER JOIN MasterUsersRole MUR ON MU.UserCode = MUR.UserCode
INNER JOIN MasterRole MR ON MUR.RoleId = MR.Id
WHERE MR.Code = #RoleUser
)
)
) RT on R.ID = RT.RequestID
) as MyHistory
inner join MasterFlow F on MyHistory.FlowID = F.ID
inner join
(
select FP.ID
, FP.Name
, FP.AssignType
, FP.AssignTo
, FP.IsStart
, case FP.AssignType
when 'GROUP' then
G.Name
end as 'AssignToName'
from MasterFlowProcess FP
left join dbo.MasterRole G on FP.AssignTo = G.ID and FP.AssignType = 'GROUP'
) FP on MyHistory.FlowProcessID = FP.ID
inner join MasterFlowProcessStatus FPS on MyHistory.FlowProcessStatusID = FPS.ID
left join MasterFlowProcessStatusNext FPSN on FPS.ID = FPSN.ProcessStatusFlowID
left join MasterFlowProcess FPN on FPSN.NextProcessFlowID = FPN.ID
left JOIN MasterRole MR ON MR.Id = FPN.AssignTo
left join MasterUsersRole MUR on MR.Id = MUR.RoleId
left join MasterUsers MURO on MUR.UserCode = MURO.UserCode
inner join MasterUsers UC on MyHistory.CreatedBy = UC.UserCode
left join MasterUsers UU on MyHistory.UpdatedBy = UU.UserCode
LEFT JOIN RequestMT RMT ON MyHistory.ID = RMT.RequestID
LEFT JOIN RequestGT RGT ON MyHistory.ID = RGT.RequestID
left join (SELECT sum(QtyCU) countQty , RequestId from dbo.RequestGTDetail where IsActive = 1 group by RequestId) RGTD on RGTD.RequestId = RGT.RequestId
left join (SELECT sum(QtyPCS) countQty , RequestId from dbo.RequestMTDetail where IsActive = 1 group by RequestId) RMTD on RMTD.RequestId = RMT.RequestId
left join (SELECT COUNT(IIF(returnable = 0, returnable, null)) countReturnable , RequestId from dbo.RequestMTDetail group by RequestId) RMTR on RMTR.RequestId = RMT.RequestId
left JOIN dbo.MasterDistributor md ON md.Code = RGT.CustId or md.Code = RMT.CustId
left JOIN dbo.MasterUsersDistributor MUD ON MUD.UserCode = MURO.UserCode AND md.Code = MUD.DistributorCode
LEFT JOIN dbo.MasterReason MRMT ON RMT.ReasonId = MRMT.Id
LEFT JOIN dbo.MasterReason MRGT ON RGT.ReasonId = MRGT.Id
LEFT JOIN dbo.MasterDistributorGroup MDG ON MDG.Id = MD.GroupId
OUTER APPLY dbo.FnGetHistoryApproveDate(MyHistory.Id) AS x
where REPLACE(FPS.Name, '#Requestor', uc.Name) <> 'DRAFT'
AND MUD.DistributorCode IN (SELECT DistributorCode FROM dbo.MasterUsersDistributor WHERE UserCode = #UserLoginID)
i want to add some logic in where clause
this line
==> AND MUD.DistributorCode IN (SELECT DistributorCode FROM dbo.MasterUsersDistributor WHERE UserCode = #UserLoginID)
it depend on the #RoleUser variable, if #RoleUser IN ('A','B') then where clause above is executed, but if #RoleUser Not IN ('A','B') where clause not executed
i,m trying this where clause
AND IIF(#RoleUser IN ('A','B'), MUD.DistributorCode, #RoleUser) IN (SELECT DistributorCode FROM dbo.MasterUsersDistributor WHERE UserCode = IIF(#RoleUser IN ('A','B'), #UserLoginID, NULL))
it didn't work, only executed if #RoleUser IS ('A','B') other than that it return 0 record
any help or advice is really appreciated
thank you
The cleanest way I'm implemented these kind of crazy rules is a
holderTable
and a countVariable against the holder table.
I'll give a generic examples.
This is a "approach" and "philosophy", not a specific answer....with complex WHERE clauses.
DECLARE #customerCountryCount int
DECLARE #customerCountry TABLE ( CountryName varchar(15) )
if ( "the moon is blue on tuesday" ) /* << whatever rules you have */
BEGIN
INSERT INTO #customerCountry SELECT "Honduras" UNION ALL SELECT "Malaysia"
END
if ( "favorite color = green" ) /* << whatever rules you have */
BEGIN
INSERT INTO #customerCountry SELECT "Greenland" UNION ALL SELECT "Peru"
END
SELECT #customerCountryCount = COUNT(*) FROM #customerCountry
Select * from dbo.Customers c
WHERE
(#customerCountryCount = 0)
OR
( exists (select null from #customerCountry innerVariableTable where UPPER(innerVariableTable.CountryName) = UPPER(c.Country) ))
)
This way, instead of putting all the "twisted logic" in an overly complex WHERE statement..... you have "separation of concerns"...
Your inserts into #customerCountry are separated from your use of #customerCountry.
And you have the #customerCountryCount "trick" to distinguish when nothing was used.
You can add a #customerCountryNotExists table as well, and code it to where not exists.
As a side note, you may want to try using a #temp table (instead of a #variabletable (#customerCountry above)... and performance test these 2 options.
There is no "single answer". You have to "try it out".
And many many variables go into #temp table performance (from a sql-server SETUP, not "how you code a stored procedure". That is way outside the scope of this question.
Here is a SOF link to "safe" #temp table usage.
Temporary table in SQL server causing ' There is already an object named' error
I need to execute a statement that follows a given Prefix.
We use a certain program, it features a 'Search Folder'. Into the Search folder, I can define an SQL query. The Folder has a built-in part of the query, which I can not modify.
The built-in part is:
Prefix Artikelfilter: SELECT * FROM CMKAT.ART WHERE 1=1 AND
Now I would like to perform the following search query:
select * from CMKAT.ART
join CMKAT.AEZ on art.artKEYI = aez.aezartkeyi
join pro on pro.prokeyi = aez.aezprokeyi
left outer join psz on pro.prokeyi = psz.pszprokeyi
WHERE psz.pszprokeyi is null
AND pro.proetykeyi = 1;
Of course, the 'SELECT *...' part is redundant, but how can I get the query to work? The JOINs are after the WHERE.
I know the developers solved this issues by creating Views, and making the selection from the view, not directly in the query.
Edit:
Exception: JdbcAccess.execute failed (ORA-00904: "KVTBEZC": ungültige ID
).
SQL:
<prefix>
SELECT /* filter art */ artkeyi, artkavkeyi, artvnrs FROM art JOIN
kav ON art.artkavkeyi = kav.kavkeyi JOIN kvt ON kav.kavkvtkeyi =
kvt.kvtkeyi JOIN kat ON kav.kavkatkeyi = kat.katkeyi WHERE
(artkavkeyi IN (587, 3075, 7, 8, 592)) AND
</prefix>
1 = 0 union all select *
from cmkat.art join cmkat.aez on art.artkeyi = aez.aezartkeyi join
pro on pro.prokeyi = aez.aezprokeyi left join psz on pro.prokeyi =
psz.pszprokeyi where psz.pszprokeyi is null and pro.proetykeyi = 1
AND katkeyi = 4 AND (katspes IN (0, 3, 1, 2))/* join-dummy */ ORDER BY
artkeyi, kvtbezc (DATABASE_EXECUTE_FAILED)
I guess you need right query like this:
If exists (SELECT 1 FROM CMKAT.ART WHERE 1=1)
Begin
(
Select *
From CMKAT.ART
Inner join CMKAT.AEZ on art.artKEYI = aez.aezartkeyi
Inner join pro on pro.prokeyi = aez.aezprokeyi
Left Outer join psz on pro.prokeyi = psz.pszprokeyi
WHERE psz.pszprokeyi is null AND pro.proetykeyi = 1;
)
END
I'd construct the SQL this way:
SELECT *
FROM CMKAT.ART
WHERE 1=1 AND EXISTS (Select 1
From CMKAT.AEZ, pro
left outer join psz on pro.prokeyi = psz.pszprokeyi
Where aez.aezartkeyi = art.artKEYI and pro.prokeyi = aez.aezprokeyi and psz.pszprokeyi is null AND pro.proetykeyi = 1
);
I don't know if your tool allows such construction, but you could cheat it using union all:
select * from cmkat.art where 1 = 1 and 1 = 0
union all
select cmkat.art.*
from cmkat.art
join cmkat.aez on art.artkeyi = aez.aezartkeyi
join pro on pro.prokeyi = aez.aezprokeyi
left join psz on pro.prokeyi = psz.pszprokeyi
where psz.pszprokeyi is null and pro.proetykeyi = 1;
First line removes data of original query because of 1 = 0 condition so we get only data from second part of union.
Unfortunately you can obtain only columns of art table because your tool does not allow to change selected data. But you can change it selecting some columns from joined tables instead of art columns.
This query gets several AssignmentId's
SELECT AS2.AssignmentId
FROM dbo.AssignmentSummary AS AS2
WHERE AS2.SixweekPosition = 1 AND AS2.TeacherId = 'mggarcia'
This query gets a value for only one assignment through the variable #assignmentId
SELECT S.StudentId,
CASE WHEN OW.OverwrittenScore IS NOT NULL
THEN OW.OverwrittenScore
ELSE dbo.GetFinalScore(S.StudentId, #assignmentId)
END AS FinalScore
FROM dbo.Students AS S
LEFT JOIN dbo.OverwrittenScores AS OW
ON S.StudentId = OW.StudentID
AND OW.AssignmentId = #assignmentId
WHERE S.ClassId IN (
SELECT C.ClassId
FROM Classes AS C
WHERE C.TeacherId = #teacherId
)
As I pointed, in the last query works when you assign a value through the variable and returns a table. Now I want to get a table of several AssignmentId's from the first query.
What do I need? A Join table? I have no idea about what to do now.
AND OW.AssignmentId IN
(
SELECT AS2.AssignmentId
FROM dbo.AssignmentSummary AS AS2
WHERE AS2.SixweekPosition = 1 AND AS2.TeacherId = 'mggarcia'
)
the suggestion can be optimize if you can tell me how are the tables are related with each other.
You can combine them using in:
SELECT S.StudentId,
CASE WHEN OW.OverwrittenScore IS NOT NULL
THEN OW.OverwrittenScore
ELSE dbo.GetFinalScore(S.StudentId, #assignmentId)
END AS FinalScore
FROM dbo.Students AS S
LEFT JOIN dbo.OverwrittenScores AS OW
ON S.StudentId = OW.StudentID
AND OW.AssignmentId in (SELECT AS2.AssignmentId
FROM dbo.AssignmentSummary AS AS2
WHERE AS2.SixweekPosition = 1 AND AS2.TeacherId = 'mggarcia'
)
WHERE S.ClassId IN (
SELECT C.ClassId
FROM Classes AS C
WHERE C.TeacherId = #teacherId
)
There may be ways to simplify this query. This does a direct conversion of substituting the first query into the second.
Use APPLY operator with correlated subquery. Also you can replace CASE expression to function ISNULL.
SELECT S.StudentId,
ISNULL(o.OverwrittenScore, dbo.GetFinalScore(S.StudentId, o.AssignmentId)) AS FinalScore
FROM dbo.Students AS S
OUTER APPLY (
SELECT OW.OverwrittenScore, AS2.AssignmentId
FROM dbo.OverwrittenScores AS OW JOIN dbo.AssignmentSummary AS AS2
ON OW.AssignmentId = AS2.AssignmentId
WHERE AS2.SixweekPosition = 1 AND AS2.TeacherId = 'mggarcia'
AND S.StudentId = OW.StudentID
) o
WHERE S.ClassId IN (
SELECT C.ClassId
FROM Classes AS C
WHERE C.TeacherId = #teacherId
)
I want to be able to inner join two tables based on the result of an expression.
What I've been trying so far:
INNER JOIN CASE WHEN RegT.Type = 1 THEN TimeRegistration ELSE DrivingRegistration AS RReg
ON
RReg.RegistreringsId = R.Id
RegT is a join I made just before this join:
INNER JOIN RegistrationTypes AS RegT ON R.RegistrationTypeId = RegT.Id
This SQL-script does not work.
So all in all, if the Type is 1, then it should join on the table TimeRegistration else it should join on DrivingRegistration.
Solution:
In my select statement I performed the following joins:
INNER JOIN RegistrationTypes AS RegT ON R.RegistrationTypeId = RegT.Id
LEFT OUTER JOIN TimeRegistration AS TReg ON TReg.RegistreringsId = R.Id AND RegT.Type = 1
LEFT OUTER JOIN DrivingRegistration AS DReg ON DReg.RegistreringsId = R.Id AND RegT.Type <>1
Then I edited my where-clause to output the correct, depending on the RegType, like this:
WHERE (CASE RegT.Type WHEN 1 THEN TReg.RegistreringsId ELSE DReg.RegistreringsId END = R.Id)
Try putting both tables in the query using LEFT JOIN's
LEFT JOIN TimeRegistration TR ON r.rid = TR.Id AND RegT.type =1
LEFT JOIN DrivingRegistration DR ON r.rid = DR.Id AND RegT.type <>1
Now, in you select clause, use
CASE RegType.Type WHEN 1 THEN TR.SomeField ELSE DR.someField END as SomeField
The other option is to use dynamic SQL
You probably need to perform two left joins, one onto TimeRegistration and one onto DrivingRegistration, and return the fields you want from the appropriate join table something like this:
LEFT JOIN TimeRegistration ON TimeRegistration.RegistreringsId = R.Id
LEFT JOIN DrivingRegistration ON DrivingRegistration.RegistreringsId = R.Id
and you select statement would be something like this:
SELECT CASE WHEN RegT.Type = 1 THEN TimeRegistration.Foo ELSE DrivingRegistration.Bar END
I like what you're trying to do, but I don't think SQL is that clever.
SELECT
R.foo, tr.bar
FROM
SomeTable AS R
INNER JOIN RegistrationTypes AS RegT ON R.RegistrationTypeId = RegT.Id
AND RegT1.Type = 1
INNER JOIN TimeRegistration AS tr ON /* whatever */
UNION
SELECT
R.foo, dr.bar
FROM
SomeTable AS R
INNER JOIN RegistrationTypes AS RegT ON R.RegistrationTypeId = RegT.Id
AND RegT1.Type = 2
INNER JOIN DrivingRegistration AS dr ON /* whatever */
So I had a scenario where there were three email columns in one table (don't ask why) and any of them could be null (or empty). In this example code I will just deal with a case where it is null.
I had to join it to another table by any of the emails to retrieve the users firstname.
Here is what worked
select
m.email1,
m.email2,
m.email3,
m2.firstName
from MyTable m
left join MyOtherTable m2 on m2.Email =
case when m.email1 is null then
case when m.email2 is null then
case when m.email3 null then
'nonexistent#mydomain.com' -- i stopped here
else m.email3 end
else wm.email2 end
else m.email1 end
Obviously you would include further conditions like
case when m.email1 is null or m.email1 = '' then ...
To cover for empty values.