Hi My query is as follows, and contains a subquery within it:
ALTER PROCEDURE [dbo].[POBalance] #PONumber NVARCHAR(50)
AS
BEGIN
SELECT CASE
WHEN X.STATUS = 'False'
THEN ( SELECT A.Description
,C.qty AS POqty
,B.Qty AS PDQty
,CASE
WHEN A.partialflag = 'false'
THEN '0'
ELSE A.qty
END AS Balance
,A.Unit
,A.Unitprice
,A.Partialflag
FROM tblPOdetails AS A
INNER JOIN tblPDdetails AS B ON A.id = B.id
INNER JOIN tblpodetailshistory AS C ON A.id = C.id
WHERE A.PONo = #PONumber
)
ELSE ( SELECT A.Description
,C.qty AS POqty
,B.Qty AS PDQty
,C.qty AS Balance
,A.Unit
,A.Unitprice
,A.Partialflag
FROM tblPOdetails AS A
INNER JOIN tblPDdetails AS B ON A.id = B.id
INNER JOIN tblpodetailshistory AS C ON A.id = C.id
WHERE A.PONo = #PONumber)
END
FROM tblPOHeader AS X
WHERE x.PONo = #PONumber
END
The error i get is :
Only one expression can be specified in the select list when the subquery is not
introduced with EXISTS.
What is wrong with my query..it seems my sub query is OK.
THanks in Advance
You can not select table in case clausule. You can do it just like that (I didn't test it):
SELECT A.Description
,C.qty AS POqty
,B.Qty AS PDQty
,CASE
WHEN A.partialflag = 'false'
THEN '0'
ELSE A.qty
END AS Balance
,A.Unit
,A.Unitprice
,A.Partialflag
FROM tblPOdetails AS A
INNER JOIN tblPDdetails AS B ON A.id = B.id
INNER JOIN tblpodetailshistory AS C ON A.id = C.id
INNER JOIN tblPOHeader X ON x.PONo = A.PONo
WHERE A.PONo = #PONumber and X.STATUS = 'False'
UNION ALL
SELECT A.Description
,C.qty AS POqty
,B.Qty AS PDQty
,C.qty AS Balance
,A.Unit
,A.Unitprice
,A.Partialflag
FROM tblPOdetails AS A
INNER JOIN tblPDdetails AS B ON A.id = B.id
INNER JOIN tblpodetailshistory AS C ON A.id = C.id
INNER JOIN tblPOHeader X ON x.PONo = A.PONo
WHERE A.PONo = #PONumber and X.STATUS <> 'False'
But I think tah X.STATUS is bit - if yes you should do it just like that:
SELECT A.Description
,C.qty AS POqty
,B.Qty AS PDQty
,CASE
WHEN A.partialflag = 'false'
THEN '0'
ELSE A.qty
END AS Balance
,A.Unit
,A.Unitprice
,A.Partialflag
FROM tblPOdetails AS A
INNER JOIN tblPDdetails AS B ON A.id = B.id
INNER JOIN tblpodetailshistory AS C ON A.id = C.id
INNER JOIN tblPOHeader X ON x.PONo = A.PONo
WHERE A.PONo = #PONumber and X.STATUS = 0
UNION ALL
SELECT A.Description
,C.qty AS POqty
,B.Qty AS PDQty
,C.qty AS Balance
,A.Unit
,A.Unitprice
,A.Partialflag
FROM tblPOdetails AS A
INNER JOIN tblPDdetails AS B ON A.id = B.id
INNER JOIN tblpodetailshistory AS C ON A.id = C.id
INNER JOIN tblPOHeader X ON x.PONo = A.PONo
WHERE A.PONo = #PONumber and X.STATUS <> 0
Are you actually looking for this?
ALTER PROCEDURE [dbo].[POBalance] #PONumber NVARCHAR(50)
AS
BEGIN
DECLARE #Status NVARCHAR(MAX)
SELECT #Status = X.STATUS
FROM tblPOHeader AS X WHEREx.PONo = #PONumber
IF #Status = 'False'
BEGIN
SELECT A.Description
,C.qty AS POqty
,B.Qty AS PDQty
,CASE
WHEN A.partialflag = 'false'
THEN '0'
ELSE A.qty
END AS Balance
,A.Unit
,A.Unitprice
,A.Partialflag
FROM tblPOdetails AS A
INNER JOIN tblPDdetails AS B ON A.id = B.id
INNER JOIN tblpodetailshistory AS C ON A.id = C.id
WHERE A.PONo = #PONumber
END
ELSE
BEGIN
SELECT A.Description
,C.qty AS POqty
,B.Qty AS PDQty
,C.qty AS Balance
,A.Unit
,A.Unitprice
,A.Partialflag
FROM tblPOdetails AS A
INNER JOIN tblPDdetails AS B ON A.id = B.id
INNER JOIN tblpodetailshistory AS C ON A.id = C.id
WHERE A.PONo = #PONumber
END
END
This code will store and then check the value of #Status and based on if the value is False or not then it will return the result set of one of the queries.
You cannot select multiple fields for one expression.Your alias makes it more visible.You select more than one value and give only one alias name!!
Please refer this
Only One Expression in case
And this one too
Another one here
When
select * from tblPOHeader where PONo = #PONumber
returns only one row you can do something like that
declare #STATUS nvarchar(200) = ( select STATUS from tblPOHeader where PONo = #PONumber)
if #STATUS = 'False'
SELECT A.Description
,C.qty AS POqty
,B.Qty AS PDQty
,CASE
WHEN A.partialflag = 'false'
THEN '0'
ELSE A.qty
END AS Balance
,A.Unit
,A.Unitprice
,A.Partialflag
FROM tblPOdetails AS A
INNER JOIN tblPDdetails AS B ON A.id = B.id
INNER JOIN tblpodetailshistory AS C ON A.id = C.id
WHERE A.PONo = #PONumber
ELSE
SELECT A.Description
,C.qty AS POqty
,B.Qty AS PDQty
,C.qty AS Balance
,A.Unit
,A.Unitprice
,A.Partialflag
FROM tblPOdetails AS A
INNER JOIN tblPDdetails AS B ON A.id = B.id
INNER JOIN tblpodetailshistory AS C ON A.id = C.id
WHERE A.PONo = #PONumber
Related
I have written 3 stored procedures and all run fine when executed in SQL Server. However, when I execute them in Visual Studio 2012 they just "spin", creating locks, etc. Any ideas?
Here is one of them. Another one is selecting values from an inline view based on the same SQL and not inserting into #temp
#StartDate As DateTime,
#EndDate As DateTime,
#EmployeeCode As VarChar(50) = NULL
AS
BEGIN
SET NOCOUNT ON;
select * into #temp
from
(SELECT e.Code AS EMPLOYEE_ID,
e.FirstName AS FIRST_NAME,
e.LastName AS LAST_NAME,
ec1.TransactionDate AS DATE_OF_SHIFT,
ou.Code AS DEPT_UNIT_CODE,
CASE
WHEN ec1.Classification = '1' THEN
MIN(ec1.TransactionDate)
END AS CLOCK_IN,
CASE
WHEN ec2.Classification = '2' THEN
MAX(ec2.TransactionDate)
END AS CLOCK_OUT,
pc.code,
epb.hourvalue
FROM APIHealthcare_History_Live.dbo.Employee e (nolock)
JOIN APIHealthcare_Live.dbo.EmployeeClocking ec1 (nolock)
ON ec1.EmployeeID = e.ID
JOIN APIHealthcare_Live.dbo.EmployeeClocking ec2 (nolock)
ON ec1.OutClockingGuid = ec2.Guid
JOIN APIHealthcare_Live.dbo.OrganizationUnit ou (nolock)
ON ec1.OrganizationUnitID = ou.ID
LEFT JOIN APIHealthcare_Live.dbo.EmployeePremiumBucket epb (nolock)
ON ec1.Guid = epb.TransactionGuid
JOIN APIHealthcare_Live.dbo.PayCode pc (nolock)
ON epb.PayCodeID = pc.ID
JOIN APIHealthcare_Live.dbo.PayGroupInstance pgi (nolock)
ON pgi.ID = epb.PayGroupInstanceID
WHERE
ec1.transactiondate between #StartDate and #EndDate
and epb.PaymentClassification = '1'
AND e.code = #EmployeeCode
AND e.ArchiveTaskID =
(
SELECT MAX(e2.ArchiveTaskID)
FROM APIHealthcare_History_Live.dbo.Employee e2 (NOLOCK)
WHERE e2.ID = e.ID
)
GROUP BY e.Code,
e.FirstName,
e.LastName,
ec1.TransactionDate,
ou.Code,
ec1.Classification,
ec2.Classification,
pc.code,
epb.hourvalue
UNION
SELECT e.Code AS EMPLOYEE_ID,
e.FirstName AS FIRST_NAME,
e.LastName AS LAST_NAME,
ec1.TransactionDate AS DATE_OF_SHIFT,
ou.Code AS DEPT_UNIT_CODE,
CASE
WHEN ec1.Classification = '1' THEN
MIN(ec1.TransactionDate)
END AS CLOCK_IN,
CASE
WHEN ec2.Classification = '2' THEN
MAX(ec2.TransactionDate)
END AS CLOCK_OUT,
pc.code,
epb.hourvalue
FROM APIHealthcare_History_Live.dbo.Employee e (nolock)
JOIN APIHealthcare_History_Live.dbo.EmployeeClocking ec1 (nolock)
ON ec1.EmployeeID = e.ID
JOIN APIHealthcare_History_Live.dbo.EmployeeClocking ec2 (nolock)
ON ec1.OutClockingGuid = ec2.Guid
JOIN APIHealthcare_History_Live.dbo.OrganizationUnit ou (nolock)
ON ec1.OrganizationUnitID = ou.ID
LEFT JOIN APIHealthcare_History_Live.dbo.EmployeePremiumBucket epb (nolock)
ON ec1.Guid = epb.TransactionGuid
JOIN APIHealthcare_History_Live.dbo.PayCode pc (nolock)
ON epb.PayCodeID = pc.ID
JOIN APIHealthcare_History_Live.dbo.PayGroupInstance pgi (nolock)
ON pgi.ID = epb.PayGroupInstanceID
WHERE
ec1.transactiondate between #StartDate and #EndDate
and epb.PaymentClassification = '1'
AND e.code = #EmployeeCode
AND e.ArchiveTaskID =
(
SELECT MAX(e2.ArchiveTaskID)
FROM APIHealthcare_History_Live.dbo.Employee e2 (NOLOCK)
WHERE e2.ID = e.ID
)
AND ou.ArchiveTaskID =
(
SELECT MAX(ou2.ArchiveTaskID)
FROM APIHealthcare_History_Live.dbo.OrganizationUnit ou2 (NOLOCK)
WHERE ou2.ID = ou.ID
)
AND pc.ArchiveTaskID =
(
SELECT MAX(pc2.ArchiveTaskID)
FROM APIHealthcare_History_Live.dbo.PayCode pc2 (NOLOCK)
WHERE pc2.ID = pc.ID
)
GROUP BY e.Code,
e.FirstName,
e.LastName,
ec1.TransactionDate,
ou.Code,
ec1.Classification,
ec2.Classification,
pc.code,
epb.hourvalue) as X
select EMPLOYEE_ID,
FIRST_NAME,
LAST_NAME,
DATE_OF_SHIFT,
DEPT_UNIT_CODE,
CLOCK_IN,
CLOCK_OUT,
code,
sum(hourvalue) as Hours
from #temp
group by EMPLOYEE_ID,
FIRST_NAME,
LAST_NAME,
DATE_OF_SHIFT,
DEPT_UNIT_CODE,
CLOCK_IN,
CLOCK_OUT,
CODE
Order by CLOCK_OUT
END
Here is the other one.
#StartDate As DateTime,
#EndDate As DateTime,
#EmployeeCode As VarChar(50) = NULL
AS
BEGIN
SET NOCOUNT ON;
select EMPLOYEE_ID,
FIRST_NAME,
LAST_NAME,
DATE_OF_SHIFT,
DEPT_UNIT_CODE,
CLOCK_IN,
CLOCK_OUT,
code,
sum(hourvalue) as Hours
from
(
SELECT e.Code AS EMPLOYEE_ID,
e.FirstName AS FIRST_NAME,
e.LastName AS LAST_NAME,
ec1.TransactionDate AS DATE_OF_SHIFT,
ou.Code AS DEPT_UNIT_CODE,
CASE
WHEN ec1.Classification = '1' THEN
MIN(ec1.TransactionDate)
END AS CLOCK_IN,
CASE
WHEN ec2.Classification = '2' THEN
MAX(ec2.TransactionDate)
END AS CLOCK_OUT,
pc.code,
epb.hourvalue
FROM APIHealthcare_History_Live.dbo.Employee e
JOIN APIHealthcare_Live.dbo.EmployeeClocking ec1
ON ec1.EmployeeID = e.ID
JOIN APIHealthcare_Live.dbo.EmployeeClocking ec2
ON ec1.OutClockingGuid = ec2.Guid
JOIN APIHealthcare_Live.dbo.OrganizationUnit ou
ON ec1.OrganizationUnitID = ou.ID
LEFT JOIN APIHealthcare_Live.dbo.EmployeePremiumBucket epb
ON ec1.Guid = epb.TransactionGuid
JOIN APIHealthcare_Live.dbo.PayCode pc
ON epb.PayCodeID = pc.ID
JOIN APIHealthcare_Live.dbo.PayGroupInstance pgi
ON pgi.ID = epb.PayGroupInstanceID
WHERE ec1.transactiondate between #StartDate and #EndDate
and epb.PaymentClassification = '1'
AND e.code = #EmployeeCode
AND e.ArchiveTaskID =
(
SELECT MAX(e2.ArchiveTaskID)
FROM APIHealthcare_History_Live.dbo.Employee e2 (NOLOCK)
WHERE e2.ID = e.ID
)
GROUP BY e.Code,
e.FirstName,
e.LastName,
ec1.TransactionDate,
ou.Code,
ec1.Classification,
ec2.Classification,
pc.code,
epb.hourvalue
UNION
SELECT e.Code AS EMPLOYEE_ID,
e.FirstName AS FIRST_NAME,
e.LastName AS LAST_NAME,
ec1.TransactionDate AS DATE_OF_SHIFT,
ou.Code AS DEPT_UNIT_CODE,
CASE
WHEN ec1.Classification = '1' THEN
MIN(ec1.TransactionDate)
END AS CLOCK_IN,
CASE
WHEN ec2.Classification = '2' THEN
MAX(ec2.TransactionDate)
END AS CLOCK_OUT,
pc.code,
epb.hourvalue
FROM APIHealthcare_History_Live.dbo.Employee e
JOIN APIHealthcare_History_Live.dbo.EmployeeClocking ec1
ON ec1.EmployeeID = e.ID
JOIN APIHealthcare_History_Live.dbo.EmployeeClocking ec2
ON ec1.OutClockingGuid = ec2.Guid
JOIN APIHealthcare_History_Live.dbo.OrganizationUnit ou
ON ec1.OrganizationUnitID = ou.ID
LEFT JOIN APIHealthcare_History_Live.dbo.EmployeePremiumBucket epb
ON ec1.Guid = epb.TransactionGuid
JOIN APIHealthcare_History_Live.dbo.PayCode pc
ON epb.PayCodeID = pc.ID
JOIN APIHealthcare_History_Live.dbo.PayGroupInstance pgi
ON pgi.ID = epb.PayGroupInstanceID
WHERE ec1.transactiondate between #StartDate and #EndDate
and epb.PaymentClassification = '1'
AND e.code = #EmployeeCode
AND e.ArchiveTaskID =
(
SELECT MAX(e2.ArchiveTaskID)
FROM APIHealthcare_History_Live.dbo.Employee e2 (NOLOCK)
WHERE e2.ID = e.ID
)
AND ou.ArchiveTaskID =
(
SELECT MAX(ou2.ArchiveTaskID)
FROM APIHealthcare_History_Live.dbo.OrganizationUnit ou2 (NOLOCK)
WHERE ou2.ID = ou.ID
)
AND pc.ArchiveTaskID =
(
SELECT MAX(pc2.ArchiveTaskID)
FROM APIHealthcare_History_Live.dbo.PayCode pc2 (NOLOCK)
WHERE pc2.ID = pc.ID
)
GROUP BY e.Code,
e.FirstName,
e.LastName,
ec1.TransactionDate,
ou.Code,
ec1.Classification,
ec2.Classification,
pc.code,
epb.hourvalue) as X
group by
EMPLOYEE_ID,
FIRST_NAME,
LAST_NAME,
DATE_OF_SHIFT,
DEPT_UNIT_CODE,
CLOCK_IN,
CLOCK_OUT,
code
order by date_of_shift, code
END
They are different execution environments. And yes, read Sommarskog's article already recommended. But I think main reason why these procedures will be slow (and not consistently) is the UNION operator. You should use UNION ALL.
Second, get rid of these (nolock) hints. They don't help you. If you really need that, you should use
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
at the beginning of your procedure. It does the same.
I have a user that wants summed data on a report. I am able to get the correct data using two separate SQL Queries and they are as follows.
SELECT JH.ProjectID, SUM(EstProdHours) AS EstProdHrs, SUM(ActProdHours)
AS ActProdHrs
FROM JobOper AS JO INNER JOIN JobHead AS JH ON JO.Company = JH.Company AND
JO.JobNum = JH.JobNum WHERE JH.ProjectID <> ''
GROUP BY JH.ProjectID ORDER BY JH.ProjectID
SELECT JH.ProjectID, SUM(EstProdHours) + SUM(EstSetHours) AS Earned
FROM JobOper AS JO INNER JOIN JobHead AS JH ON JO.Company = JH.Company AND
JO.JobNum = JH.JobNum WHERE JH.ProjectID <> '' AND OpComplete = 1
GROUP BY JH.ProjectID ORDER BY JH.ProjectID
This two individual queries deliver the correct data on their own. My goal however, is to setup a SQL view with the results of these two queries together with result as shown below:
ProjectID EstProdHrs ActProdHrs Earned
6000 480.00 1640.59 477
6001 621.00 2431.04 619
6002 6687.97 23234.23 6695.47
6003 414.97 4731.47 416.72
6004 208.00 2196.52 206.00
6005 2.00 76.77 NULL <--- This would show up if no completed ops in 2nd select statement
6006 20.83 819.29 18.83
I have tried to inner join the two queries and I can't seem to avoid "incorrect syntax errors". Here is that statement:
SELECT * FROM
(SELECT JH.ProjectID, SUM(EstProdHours) AS EstProdHrs, SUM(ActProdHours) AS
ActProdHrs,'N/A' AS ValueMissingTableB
FROM JobOper AS JO INNER JOIN JobHead AS JH ON JO.Company = JH.Company AND
JO.JobNum = JH.JobNum WHERE JH.ProjectID <> ''
) AS 1
INNER JOIN
(SELECT JH2.ProjectID, SUM(EstProdHours) + SUM(EstSetHours) AS Earned
FROM JobOper AS JO2 INNER JOIN JobHead AS JH2 ON JO2.Company = JH2.Company
AND JO2.JobNum = JH2.JobNum WHERE JH2.ProjectID <> '' AND OpComplete = 1
) AS 2
ON 1.ProjectID = 2.ProjectID
I have also tried UNION and UNION ALL and it fails because the two queries don't have the same amount of records. I am hoping I am making a rookie mistake here and this can be done. Thanks for any insight.
Try this :
WITH A AS (SELECT JH.ProjectID, SUM(EstProdHours) AS EstProdHrs, SUM(ActProdHours) AS
ActProdHrs,'N/A' AS ValueMissingTableB
FROM JobOper AS JO INNER JOIN JobHead AS JH ON JO.Company = JH.Company AND
JO.JobNum = JH.JobNum WHERE JH.ProjectID <> ''
GROUP BY JH.ProjectID ORDER BY JH.ProjectID
),
B AS
(SELECT JH2.ProjectID, SUM(EstProdHours) + SUM(EstSetHours) AS Earned
FROM JobOper AS JO2 INNER JOIN JobHead AS JH2 ON JO2.Company = JH2.Company
AND JO2.JobNum = JH2.JobNum WHERE JH2.ProjectID <> '' AND OpComplete = 1
GROUP BY JH2.ProjectID ORDER BY JH2.ProjectID
)
SELECT * FROM A
JOIN B ON A.ProjectID = B.ProjectID
I don't have your tables to test this but cant you just do a left join;
SELECT A.ProjectID,A.EstProdHrs, A.ActProdHrs, E.Earned
FROM (
SELECT JH.ProjectID, SUM(EstProdHours) AS EstProdHrs, SUM(ActProdHours) AS ActProdHrs
FROM JobOper AS JO INNER JOIN JobHead AS JH ON JO.Company = JH.Company AND
JO.JobNum = JH.JobNum WHERE JH.ProjectID <> ''
GROUP BY JH.ProjectID
) A
LEFT JOIN (
SELECT JH.ProjectID, SUM(EstProdHours) + SUM(EstSetHours) AS Earned
FROM JobOper AS JO INNER JOIN JobHead AS JH ON JO.Company = JH.Company AND
JO.JobNum = JH.JobNum WHERE JH.ProjectID <> '' AND OpComplete = 1
GROUP BY JH.ProjectID
) E
ON A.ProjectID=E.ProjectID
ORDER BY A.ProjectID
SELECT a.name,
nvl(c.bill_amount,0),
b.status
FROM table_1 a left outer join table_2 b
ON a.name = b.name and
b.status = 'YES'
left outer join table_3 c on B.phone_number = C.phone_number
AND B.email = C.email
where
a.VALID = 'Y';
I wrote this query recently, the condition b.status = 'yes' is not fulfilled in the above query and status shows NULL value in it. I want to refine my records according to this condition b.status ='yes'.
Try the following:
SELECT a.name, nvl(c.bill_amount,0), b.status
FROM table_1 a left outer join table_2 b
ON a.name = b.name
left outer join table_3 c on b.phone_number = c.phone_number
where
a.VALID = 'Y' and
b.status = 'YES' and
b.email = c.email
I have this query:-
select distinct pav.ProductID,pav.String_Value as Description ,pav1.String_Value as StockNumber,pav2.String_Value as ProductImage,
pav3.String_Value as SpecSheet,pav4.String_Value as Price
from core.ProductAttributesValues pav join core.Attribute a on pav.AttributeID=a.ID and a.Name='Description'
inner join core.ProductAttributesValues pav1 on pav1.ProductID=pav.ProductID
inner join core.Attribute a1 on pav1.AttributeID=a1.ID and a1.Name='StockNumber'
inner join core.ProductAttributesValues pav2 on pav2.ProductID=pav1.ProductID
inner join core.Attribute a2 on pav2.AttributeID=a2.ID and a2.Name='ProductImage'
inner join core.ProductAttributesValues pav3 on pav3.ProductID=pav2.ProductID
inner join core.Attribute a3 on pav3.AttributeID=a3.ID and a3.Name='SpecSheet'
inner join core.ProductAttributesValues pav4 on pav4.ProductID=pav3.ProductID
inner join core.Attribute a4 on pav4.AttributeID=a4.ID and a4.Name='Price'
I want to pass a1.Names(i.e:- Description ,StockNumber, ProductImage, etc), dynamically.
Try this...
SELECT
pav.ProductID
,CASE WHEN a.Name = 'Description' THEN pav.String_Value ELSE NULL END AS Description
,CASE WHEN a.Name = 'StockNumber' THEN pav.String_Value ELSE NULL END AS StockNumber
,CASE WHEN a.Name = 'ProductImage' THEN pav.String_Value ELSE NULL END AS ProductImage
,CASE WHEN a.Name = 'SpecSheet' THEN pav.String_Value ELSE NULL END AS SpecSheet
,CASE WHEN a.Name = 'Price' THEN pav.String_Value ELSE NULL END AS Price
FROM core.ProductAttributesValues pav
INNER JOIN core.Attribute a ON pav.AttributeID = a.ID
AND a.name IN ('Description', 'StockNumber', 'ProductImage', 'SpecSheet','Price')
Have query like :
declare #case int = 1
SELECT a.column1,b.column2
FROM tbl1 a
INNER JOIN tbl2 b on a.id = b.id and a.category in(1,2,3,4,5)
Need when #case = 1 category must be in (1,2,3,4,5), when #case = 2 it must be (1,2,4,5).
Something like this :
SELECT a.column1,b.column2
FROM tbl1 a
INNER JOIN tbl2 b on a.id = b.id and (CASE WHEN #case = 1 THEN a.category in(1,2,3,4,5) WHEN #case = 2 THEN (1,2,4,5) ELSE '')
How to do it ?
SELECT a.column1,b.column2
FROM tbl1 a
INNER JOIN tbl2 b on a.id = b.id
and
(
(#case = 1 and a.category in (1,2,3,4,5)) OR
(#case = 2 and a.category in (1,2,4,5))
)
I added parentheses for readability. Not all of them are necessary.
The other answer is better but if you did happen to want to do it with case you could do it like
SELECT a.column1,b.column2
FROM tbl1 a
INNER JOIN tbl2 b on a.id = b.id and
( CASE WHEN #case = 1 and a.category in(1,2,3,4,5) THEN 1
WHEN #case = 2 and a.category in(1,2,3,4) THEN 1
ELSE 0
END
) = 1