Stored Procedure using where with multiple if else and different table - sql

ALTER PROCEDURE [dbo].[SP_Something]
(
#Search_Text VARCHAR(4000),
#FILTER INT
)
AS
BEGIN
SELECT Customer_Information
FROM Customer
LEFT OUTER JOIN Something K
ON K.Something _Id= Something_Id2
LEFT OUTER JOIN Something3 KS
ON KS.Something_Id =Something_Id3
WHERE
(Filter = 1 AND Customer_İnformation LIKE '%' + #Search_Text + '%')
OR
(Filter = 2 AND Customer_name LIKE '%' + #Search_Text + '%')
OR
(Filter = 3 AND Customer_Adress LIKE '%' + #Search_Text + '%')
END
I get all datas from Customer Table.
I need to get data from PRODUCT_TABLE for my below code,
(Filter = 3 AND Customer_Adress LIKE '%' + #Search_Text + '%')
from PRODUCT_TABLE
how can i achieve this inside "where" in Ms Sql?
Any help will be appreciated.
Thanks.

ALTER PROCEDURE [dbo].[SP_Something]
(
#Search_Text VARCHAR(4000),
#FILTER INT
)
AS
BEGIN
IF Filter IN (1,2)
SELECT Customer_Information
FROM Customer
LEFT OUTER JOIN Something K
ON K.Something _Id= Something_Id2
LEFT OUTER JOIN Something3 KS
ON KS.Something_Id =Something_Id3
WHERE
(Filter = 1 AND Customer_İnformation LIKE '%' + #Search_Text + '%')
OR
(Filter = 2 AND Customer_name LIKE '%' + #Search_Text + '%')
OR
(Filter = 3 AND Customer_Adress LIKE '%' + #Search_Text + '%')
IF Filter = 3
SELECT YourField
FROM ProductTable
WHERE
(Filter = 3 AND YourSearchField LIKE '%' + #Search_Text + '%')
END

ALTER PROCEDURE [dbo].[SP_Something]
(
#Search_Text VARCHAR(4000),
#FILTER INT
)
AS
BEGIN
SELECT Customer_Information
FROM Customer
LEFT OUTER JOIN Something K
ON K.Something _Id= Something_Id2
LEFT OUTER JOIN Something3 KS
ON KS.Something_Id =Something_Id3
LEFT OUTER JOIN PRODUCT_TABLE P
ON P.Something_Id = KS.Something_Id3
WHERE
(Filter = 1 AND Customer_İnformation LIKE '%' + #Search_Text + '%')
OR
(Filter = 2 AND Customer_name LIKE '%' + #Search_Text + '%')
OR
(Filter = 3 AND Customer_Adress LIKE '%' + #Search_Text + '%')
OR
(P.Filter = 3 AND P.Customer_Adress LIKE '%' + #Search_Text + '%')
END
I think another thing you are missing here is, in your Where clause you havent mentioned anything about which Filter is from which table, Use the table alias before the column names like I have it makes code easier to read and easier to maintain and resolves column ambiguity .

Related

Stored Procedure using Where with if else

I have been trying to use stored procedure for searching data.
ALTER PROCEDURE [dbo].[SP_Something]
(
#Search_Text VARCHAR(4000),
#FILTER INT
)
AS
BEGIN
SELECT Customer_Information
FROM Customer
LEFT OUTER JOIN Something K ON K.Something _Id= Something_Id2
LEFT OUTER JOIN Something3 KS ON KS.Something_Id =Something_Id3
WHERE
// If #FILTER=1 i want to search below
Customer_İnformation LIKE '%' + #Search_Text + '%'
// If #FILTER=2 i want to search below
Customer_name LIKE '%' + #Search_Text + '%'
// If #FILTER=3 i want to search below
Customer_Adress LIKE '%' + #Search_Text + '%'
How can i use Where with If conditions ?
Any help will be appreciated
Thank you.
ALTER PROCEDURE [dbo].[SP_Something]
(
#Search_Text VARCHAR(4000),
#FILTER INT
)
AS
BEGIN
SELECT Customer_Information
FROM Customer
LEFT OUTER JOIN Something K
ON K.Something _Id= Something_Id2
LEFT OUTER JOIN Something3 KS
ON KS.Something_Id =Something_Id3
WHERE
(Filter = 1 AND Customer_İnformation LIKE '%' + #Search_Text + '%')
OR
(Filter = 2 AND Customer_name LIKE '%' + #Search_Text + '%')
OR
(Filter = 3 AND Customer_Adress LIKE '%' + #Search_Text + '%')
END
ALTER PROCEDURE [dbo].[SP_Something]
(
#Search_Text VARCHAR(4000),
#FILTER INT
)
AS
BEGIN
SELECT Customer_Information
FROM Customer
LEFT OUTER JOIN Something K ON K.Something _Id= Something_Id2
LEFT OUTER JOIN Something3 KS ON KS.Something_Id =Something_Id3
WHERE
CASE #FILTER
WHEN 1 THEN Customer_İnformation
WHEN 2 THEN Customer_Name
WHEN 3 THEN Customer_Address
END LIKE '%' + #Search_Text + '%';
END

SELECT DISTINCT with COUNT

I want to count the number of patients that are not currently admitted (CurrentClinicalInfo = 'False'). However, there are multiple ClinicalInfos per patient. Therefore I need to select distinctively.
I have tried this code below but it comes with too many column leading to errors further on.
SELECT DISTINCT COUNT(*) AS TableLength
FROM PatientDemographics AS p LEFT OUTER JOIN
PatientClinicalinformation AS pc ON p.PatientID = pc.PatientID
WHERE (pc.PatientID IS NULL) AND (p.FirstName LIKE '%' + + '%') OR
(pc.PatientID IS NULL) AND (p.Surname LIKE '%' + + '%') OR
(p.FirstName LIKE '%' + + '%') AND (pc.CurrentClinicalInfo = 'False') OR
(p.Surname LIKE '%' + + '%
') AND (pc.CurrentClinicalInfo = 'False')
You want distinct Patients, correct?
SELECT COUNT(DISTINCT p.PatientID) AS TableLength
FROM PatientDemographics AS p
LEFT JOIN PatientClinicalinformation AS pc ON p.PatientID = pc.PatientID
WHERE pc.PatientID IS NULL AND p.FirstName LIKE '%' + #input + '%'
OR
pc.PatientID IS NULL AND p.Surname LIKE '%' + #input + '%'
OR
p.FirstName LIKE '%' + #input + '%' AND pc.CurrentClinicalInfo = 'False'
OR
p.Surname LIKE '%' + #input + '%' AND pc.CurrentClinicalInfo = 'False'

Using result of a SQL WITH statement more than once in a stored procedure

I have the SQL stored procedure below:
ALTER PROCEDURE [dbo].[sp_getpaginatedusersbyglobalfilter]
#globalFilter varchar(max)
, #pageSize int
, #page int
, #totalRecords int output
, #totalFilteredRecords int output
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
;WITH PaginatedUsers AS(
SELECT ROW_NUMBER() OVER(ORDER BY u.LastName) ID
, u.Username
, u.FirstName
, u.OtherNames
, u.LastName
, e.Nombre
, r.RoleName
, u.PhoneNumber
FROM webpages_Users u
INNER JOIN Establecimiento e
ON u.FacilityId = e.IDReporte
AND e.EstadoRegistro = 1
INNER JOIN webpages_UsersInRoles ur
ON u.UserId = ur.UserId
INNER JOIN webpages_Roles r
ON ur.RoleId = r.RoleId
WHERE u.Username LIKE '%' + #globalFilter + '%'
OR u.FirstName LIKE '%' + #globalFilter + '%'
OR u.OtherNames LIKE '%' + #globalFilter + '%'
OR u.LastName LIKE '%' + #globalFilter + '%'
OR e.Nombre LIKE '%' + #globalFilter + '%'
OR r.RoleName LIKE '%' + #globalFilter + '%'
OR u.PhoneNumber LIKE '%' + #globalFilter + '%'
)
SELECT pu.ID, pu.Username
, pu.FirstName
, pu.OtherNames
, pu.LastName
, pu.Nombre AS FacilityName
, pu.RoleName
, pu.PhoneNumber
FROM PaginatedUsers pu
WHERE pu.ID BETWEEN ((#page - 1) * #pageSize + 1)
AND #page * #pageSize
SELECT #totalFilteredRecords = COUNT(pu.ID)
FROM PaginatedUsers pu
SELECT #totalRecords = COUNT(u.UserId)
FROM webpages_Users u
END
The problem I have is with the section:
SELECT #totalFilteredRecords = COUNT(pu.ID)
FROM PaginatedUsers pu
The error I get is "Invalid object name 'PaginatedUsers'". As per my research, I cannot use the PaginatedUsers (resulting from the WITH) object more than once in the query. Then, How can I do to return the total number of records in the output variable #totalFilteredRecords? I've been thinking about inserting the result into a temporal table and then get the count from it as well as the final resultset, but I don't like that idea. What can I do?
Thanks.
You can only use the output of a With clause in the same statement as the With clause. The first Select clause is part of the first SQL Statement that starts with the With clause. By using a second Select, it is in a separate SQL statement. If you connect the two Selects into a single statement, then it will work.
Your research is correct, you cannot use CTEs more than once.
--EDIT
AS OP points out, A SELECT statement that assigns a value to a variable must not be combined with data-retrieval operations.
So I don't have any other suggestions rather than to use a temp table -- here is an untested example:
SELECT ROW_NUMBER() OVER(ORDER BY u.LastName) ID
, u.Username
, u.FirstName
, u.OtherNames
, u.LastName
, e.Nombre
, r.RoleName
, u.PhoneNumber
INTO #PaginatedUsers
FROM webpages_Users u
INNER JOIN Establecimiento e
ON u.FacilityId = e.IDReporte
AND e.EstadoRegistro = 1
INNER JOIN webpages_UsersInRoles ur
ON u.UserId = ur.UserId
INNER JOIN webpages_Roles r
ON ur.RoleId = r.RoleId
WHERE u.Username LIKE '%' + #globalFilter + '%'
OR u.FirstName LIKE '%' + #globalFilter + '%'
OR u.OtherNames LIKE '%' + #globalFilter + '%'
OR u.LastName LIKE '%' + #globalFilter + '%'
OR e.Nombre LIKE '%' + #globalFilter + '%'
OR r.RoleName LIKE '%' + #globalFilter + '%'
OR u.PhoneNumber LIKE '%' + #globalFilter + '%'
SELECT pu.ID, pu.Username
, pu.FirstName
, pu.OtherNames
, pu.LastName
, pu.Nombre AS FacilityName
, pu.RoleName
, pu.PhoneNumber
FROM #PaginatedUsers pu
WHERE pu.ID BETWEEN ((#page - 1) * #pageSize + 1)
AND #page * #pageSize
SELECT #totalFilteredRecords = COUNT(pu.ID)
FROM #PaginatedUsers pu
SELECT #totalRecords = COUNT(u.UserId)
FROM webpages_Users u
DROP TABLE #PaginatedUsers
Here is a good answer I read about CTE vs Temp Tables.

Reading items with LIKE in a function that splits

I have a query that uses a function called "My_Splitter" when I pass a string like
"this is an example", it returns
this
is
an
example
The problem I am having in my query is that I need to take each of those values and do something like
select value from My_Splitter(#MyString) where value LIKE '%this%' or value LIKE '%is%' or value LIKE '%an%' or value like '%example%'
you get my idea... here is my query
select
DISTINCT(pr.myID)
from
myProducts pr
left JOIN pcategory pc ON pr.ProductId = pc.ProductId
left JOIN category ca on ca.categoryid = pc.categoryid
left join sNumber zs on zs.productid=pr.productid
where
pr.activated = 1
and pr.PortalId = #PortalId
and (pr.Name like '%' + #Keyword + '%'
or pr.Name in (select value from SC_Splitter(#Keyword,' ')) //PROBLEM HERE
or pr.myTitle LIKE '%' + #Keyword + '%'
or pr.PRnum LIKE '%' + #Keyword + '%'
or zs.snum like '%' + #Keyword + '%'
I WISH I COULD JUST DO
or pr.Name LIKE (select value from SC_Splitter(#Keyword,' ')) and it would take any value from #Keywprd and so a LIKE search on each :( lol
If you use Full-Text Search in Microsoft SQL Server, the difficulty goes away, and your searches will be orders of magnitude faster.
select
DISTINCT(pr.myID)
from
myProducts pr
left JOIN pcategory pc ON pr.ProductId = pc.ProductId
left JOIN category ca on ca.categoryid = pc.categoryid
left join sNumber zs on zs.productid=pr.productid
where
pr.activated = 1
and pr.PortalId = #PortalId
and (CONTAINS(pr.Name, #Keyword)
or FREETEXT(pr.Name, #Keyword) //NO PROBLEM HERE
...
Another possibility is to use CROSS APPLY.
select
DISTINCT(pr.myID)
from
myProducts pr
left JOIN pcategory pc ON pr.ProductId = pc.ProductId
left JOIN category ca on ca.categoryid = pc.categoryid
left join sNumber zs on zs.productid=pr.productid
CROSS APPLY SC_Splitter(#keyword,' ') AS sentance
where
pr.activated = 1
and pr.PortalId = #PortalId
and (pr.Name like '%' + #Keyword + '%'
OR pr.name LIKE '%' + Sentance.Value + '%')
or pr.myTitle LIKE '%' + #Keyword + '%'
or pr.PRnum LIKE '%' + #Keyword + '%'
or zs.snum like '%' + #Keyword + '%'
i suggest restructuring your splitter to a new function that can accept two strings, the name and the 'sentence'
then that function would loop over the parsed sentence to see if it matches the name and return a 1 if found, and a 0 if not.
then your query would simply have a where my_new_function( name, sentence ) = 1 line
This fixes the issue with your solution., but Bill Karwin's answer is the correct solution for the problem.
To save time and more questions, this can't be optimised. The main reason is leading wildcards. Use Full Text Search if you want "fast" as well as "working"
Basically, JOIN using LIKE
select
DISTINCT(pr.myID)
from
myProducts pr
left JOIN pcategory pc ON pr.ProductId = pc.ProductId
left JOIN category ca on ca.categoryid = pc.categoryid
left join sNumber zs on zs.productid=pr.productid
JOIN
SC_Splitter(#Keyword,' ') CSV ON pr.Name LIKE '%' + CSV.value + '%'
where
pr.activated = 1
and pr.PortalId = #PortalId
and
--fix your parenthesis after this.
--I'm not sure what was intended above
(pr.Name like '%' + #Keyword + '%'
or pr.myTitle LIKE '%' + #Keyword + '%'
or pr.PRnum LIKE '%' + #Keyword + '%'
or zs.snum like '%' + #Keyword + '%'
)

SEARCH several Tables IN SQL

I'm trying to search several tables at once for a search term. My query is:
SELECT item.ItemID
FROM Inventory.Item item
JOIN Inventory.Category catR // each item can be in several categories
ON catR.ItemID = item.ItemID
JOIN Category.Category cat
ON cat.CategoryID = catR.CategoryID
JOIN Inventory.Brand bran
ON bran.BrandID = item.BrandID
WHERE
item.Description LIKE '%' + #term + '%'
OR
item.Description LIKE '%' + #term
OR
item.Description LIKE #term + '%'
OR
item.Description = #term
OR
cat.CategoryName LIKE '%' + #term + '%'
//same pattern as item.Description used to search CategoryName
//...
OR
bran.BrandName LIKE '%' + #term + '%'
//same pattern as item.Description used to search BrandName
//...
But the results are not as expected. I have about 50 items in the category "Casement" but when term == "Casement" only items that have "Casement" in their item.Description will be returned.
Am I doing something wrong? Should I do this a better way?
Its enough to write
item.Description LIKE '%' + #term + '%'
instead of
item.Description LIKE '%' + #term + '%'
OR
item.Description LIKE '%' + #term
OR
item.Description LIKE #term + '%'
OR
item.Description = #term
Conceptually I would keep it simple and then change it from there if needed for performance. First I would create a view and then do the select off of that.
CREATE VIEW vSearchTables
AS
SELECT item.ItemID, 'Item' AS TableName, item.Descripton AS Txt
FROM Inventory.Item item
UNION ALL
SELECT catR.ItemID, 'Category' AS TableName, cat.CategoryName AS Txt
FROM Inventory.Category catR
JOIN Category.Category cat
ON cat.CategoryID = catR.CategoryID
UNION ALL
SELECT item.ItemID, 'Brand' AS TableName, bran.BrandName AS Txt
FROM Inventory.Item item
JOIN Inventory.Brand bran
ON bran.BrandID = item.BrandID
GO
SELECT ItemID
FROM vSearchTables
WHERE Txt LIKE '%'+#term +'%'
GO
If you have sql2005 and want to test this concept you can run the following:
CREATE VIEW vSearchTables
AS
select object_name(o.object_id) Object, o.type, m.definition as Txt
from sys.sql_modules m
join sys.objects o on m.object_id = o.object_id
GO
SELECT *
FROM vSearchTables
WHERE Txt LIKE '%TRIGGER%'
This is a good CTE example:
WITH items AS (
SELECT i.itemid,
i.description,
cat.category_name,
b.brandname
FROM INVENTORY.ITEM i
LEFT JOIN INVENTORY.CATEGORY c ON c.itemid = i.itemid
LEFT JOIN CATEGORY.CATEGORY cat ON cat.CategoryID = c.categoryid
LEFT JOIN INVENTORY.BRAND b ON b.brandid = i.brandid)
SELECT a.itemid
FROM items a
WHERE a.description LIKE '%' + #term + '%'
UNION ALL
SELECT b.itemid
FROM items b
WHERE b.categoryname LIKE '%' + #term + '%'
UNION ALL
SELECT c.itemid
FROM items c
WHERE c.brandname LIKE '%' + #term + '%'
CTEs are supported in SQL Server 2005+.
Try this:
Select i.ItemID
From Inventory.Item i
Join Inventory.Category ic
On ic.ItemID = i.ItemID
Join Category.Category cc
On cat.CategoryID = ic.CategoryID
Join Inventory.Brand ib
On ib.BrandID = i.BrandID
Where CharIndex(#Term,
i.Description + '|' +
ic.Description + '|' +
cc.Description + '|' +
ib.Description) > 0
Realize that this will cause a full table scan of all four tables, so it will be slow if these tables are large. But given what you are trying to do, the only alternative would be to implement full text indices on the database...
Also, if it is possiblke that one of these tables does not contain a matching row for yr join condition, you should make all the joins outer joins, and use IsNull() on all the column references...
Select i.ItemID
From Inventory.Item i
Left Join Inventory.Category ic
On ic.ItemID = i.ItemID
Left Join Category.Category cc
On cat.CategoryID = ic.CategoryID
Left Join Inventory.Brand ib
On ib.BrandID = i.BrandID
Where CharIndex(#Term,
i.Description + '|' +
IsNull(ic.Description, '') + '|' +
IsNull(cc.Description, '') + '|' +
IsNull(ib.Description, '')) > 0