Is there a way to construct a parametrised query with a where clause on a field that matches all entries in the field. For example I am imagining syntax like
'select brands from cars where brands = param'
such that if param = 'Toyota' then it only returns rows matching Toyota, but if param = * it returns all rows from the cars table.
Try this. It's a conditional WHERE clause
WHERE brands = NVL(param, brands)
Means if the param is NULL, use brands = brands
The usual workaround is
select brands from cars where brands LIKE param
If param = 'Toyota' it returns only Toyota
If param = '%' it returns everything
Simple but not necessarily performant.
select * from cars where brands like '%'||parameter||'%'
You can use distinct to get all brands from your table.
If you have a variable, you would do:
where v_brand is null or v_brand = brand
If you just want an expression that matches everything:
where 1 = 1
The proper way to return all rows regardless of brand is to remove the brands = param from your filter, not to use a wildcards or functions on it...
It is common to add where 1=1 to clauses in your case and use in the following pattern:
If param has a value
select brands from cars where 1=1 and brands = param
otherwise you just remove the and brands = param part:
select brands from cars where 1=1
Related
I have a stored procedure for the Filters of products in my website which goes like:
ALTER PROCEDURE [dbo].[sp_product_get_by_filters]
(#brand_names nvarchar(max),
#type nvarchar(max))
AS
BEGIN
SELECT
tbl_product.product_code,
tbl_product.brand_name,
tbl_product.subcategory_code,
tbl_product.product_name,
tbl_product.product_photo_1,
tbl_product.filter_code,
(select filter_name from tbl_filter where filter_code = tbl_product.filter_code )as filter_name,
(select AVG(CAST(rating AS DECIMAL(10,2))) from tbl_review where product_code = tbl_product.product_code) as Rating,
(select TOP 1 sub_product_price from tbl_sub_product where product_code = tbl_product.product_code) as product_price,
(select TOP 1 size from tbl_sub_product where product_code = tbl_product.product_code) as size,
(select TOP 1 sub_product_code from tbl_sub_product where product_code = tbl_product.product_code) as sub_product_code
FROM
tbl_product
WHERE
tbl_product.brand_name IN (SELECT * FROM dbo.splitstring(#brand_names))
AND tbl_product.filter_code IN (SELECT * FROM dbo.splitstring(#type))
END
#brand_names here is a string of the name of brands separated by comma for example
Apple,Samsung,Nokia
and #type is the filter of the products which is like
'Watch,Mobile,Tablet'
The dbo.splitstring function separates each value from the concatenated string and return the list as a table. So the problem when a User select both Brand Name and Type the query returns the values but if a user select only Brand Name or Type the query doesn't return anything. I want to make the query to return the products if the user select both Brand Name and Type or don't select any of them (You know like filters in every e-commerce website). If the user doesn't select any filter I am passing an empty string in variables like if user doesn't select any brand then #brand_names will be #brand_names = ''.
For example if a user select Brand Name Apple the query must return all the products related to this brand. And again if the user select the Type watch then the query must return the Watches from brand Apple. I am using SQL Server 2008.
Thank you for the Help.
For this kind of "optional parameter" query, an option recompile at the end can improve performance by quite a lot.
If an "unselected" parameter is an empty string, then you can do:
WHERE
(#brand_names = '' or tbl_product.brand_name IN (SELECT * from dbo.splitstring(#brand_names)))
and (#type = '' or tbl_product.filter_code IN (SELECT * from dbo.splitstring(#type)))
option (recompile)
The option (recompile) tells SQL to build a new plan for this statement every time the procedure runs. So, for example, if you pass an empty string for #brand_names, the engine doesn't even need to evaluate the or tbl_product.brand_name in ... part of that predicate. If you don't do this, then SQL will - as always - build a plan for the first execution, and then reuse that plan on subsequent executions. That's not great when different parameter values can make such a big difference to the result.
I'm just taking a look at the following query
select * from tablename
where id like '%%';
So that it can handle parameters to include all of the data or filtered data like bellow
select * from tablename
where id like '%1%';
Which is fine for most parameters I use but this seems wrong for an ID because it will return all data that has IDs containing 1 which I don't want
To get around this I can only append the where clause if the ID is given but that seems like a pain in the butt
Is it possible to use a different type of where clause so that a wildcard can be used in a where equals clause instead of a where like clause, example
select * from tablename
where id = '*';
So that the same query can be used to return all or filtered data? Pass parameter '*' for all or parameter '1' for ID 1 specifically
(I'm not sure if it matters for this case but I'm using PostgreSQL 9.6.12 in this example)
This would often be expressed as:
where (id = :id or :id is null)
null is the "magic" value that represents all rows.
Is it possible to use the input from one field of the database for another query in combination with the IN statement. The point is that in the sting, I use for IN, contains several by comma separated values:
SELECT id, name
FROM refPlant
WHERE id IN (SELECT cover
FROM meta_characteristic
WHERE id = 2);
the string of the subquery is: 1735,1736,1737,1738,1739,1740,1741,1742,1743,1744
The query above give me only the first element of the string. But when I put the string directly in the query, I get all the ten elements:
SELECT id, name
FROM refPlant
WHERE id IN (735,1736,1737,1738,1739,1740,1741,1742,1743,1744);
Is it possible to have all ten elements and not only one with query like the first one.
My sql version is 10.1.16-MariaDB
You can use FIND_IN_SET in the join condition.
SELECT r.id, r.name
FROM refPlant r
JOIN (SELECT * FROM meta_characteristic m WHERE id=2) m
ON FIND_IN_SET(r.id,m.cover) > 0
If you use a sub-query as in the first code snippet you will get a filter for each row returned from it. It will not work when it returns as a single string field.
SELECT id, name
FROM refPlant
WHERE FIND_IN_SET(id, (SELECT cover
FROM meta_charateristic
WHERE id = 2));
I have SQL Server tables and I am supposed to create a query where it will be able to draw out the same data based on any combination of inputs of parameters / search conditions in a single query
For example, a user gives a model number for us to search for all products in table 1.
I would create a query as follows:
SELECT *
FROM Products
WHERE pModel = #pUserModel;
Next, another user gives us a description of the product which I then have to create another query as follows:
SELECT *
FROM Products
WHERE pDescription = #pUserDescription;
Table 1
Products (pNo, pModel, pDescription, pQty, pGlobalQty, pParent)
My issue here would be that instead of the two queries that were created based on different parameters, is there any way to create a single query where it will be able to fulfill those two search condition by both different users?
declare #pUserModel varchar(50)
declare #pUserDescription varchar(50)
--- if you want to search with individual search parameter than try with this.
if (#pUserModel <> '')
begin
SELECT * FROM Products WHERE pModel = #pUserModel;
end
else if (#pUserDescription <> '')
begin
SELECT * FROM Products WHERE pDescription = #pUserDescription;
end
--- if you want to combine all search parameter than try with this.
SELECT * FROM Products WHERE LTRIM(RTRIM(pModel)) = #pUserModel or LTRIM(RTRIM(pDescription)) = #pUserDescription
If I understand your requirement properly, you need join and OR condition
select * from Products p
left join Model m
on p.pModel=m.mModel
where (p.pModel = #pUserModel
OR p.pDescription = #pUserDescription)
Left join to return records from Products even if there is no Model associated with it. You can change it to INNER JOIN if you don't want it.
You can look for the trimmed length of the parameter string as part of an OR condition and always provide both parameters, even if one of them is an empty string "". Something like
SELECT
P.*
from
Products P
where
( LEN( RTRIM( #pUserModel )) = 0
OR P.pModel = #pUserModel )
OR
( LEN( RTRIM( #pUserDescription )) = 0
OR P.pDescription = #pUserDescription )
if you query such as where pDescription = '', it would fail if the description column actually HAS a value. So by wrapping each in an OR condition to say it's ok if the length of the TRIMMED parameter = 0 OR it matches the one being searched for. If you want the wild-card search, be sure to add '%'
To eliminate the OR qualifier, if your empty parameters are just '%', that will pull everything, for that respective parameters. So you could have a model = '%' and description = 'Something%'... Or vice-versa... Model = 'Some Model%' and Description = '%'
I aliased the products table as "P" to simplify readability. Especially if you have multiple tables, you should always identify where a table/column comes from for others to help.
i have one table named category.
in this table i have two columns 1.) cat_id, 2.) cat_name
in this table i have added record with this value : cat_id = 1, cat_name = test
Now when i am going to run select query
SELECT * FROM category WHERE cat_name = 'Test'
this query returns me null result because in database record string is test and in query it's a Test mark the differance of capital string here. Instade of null result i want the result with 1st record.
also i want same result in vice versa small and capital string.
i am using sqlite as database.
Use upper function.
SELECT * FROM category WHERE upper(cat_name) = upper('Test')
SELECT * FROM category WHERE cat_name = 'Test' COLLATE NOCASE;
use LOWER:
SELECT * FROM category WHERE LOWER(cat_name) = 'test'
will get you all combinations of TeSt