Use dynamic parameter in SELECT query in Postgres? - sql

There is another question with this title - sorry to duplicate, but I simply cannot understand the answers to that question, so I assume plenty of others won't either and it will be useful to have a clear answer.
I am working in Postgres. I have a stored procedure called duplicate_project that takes a single parameter, the project ID.
I'd like to add a dynamic parameter in a WHERE clause in a SELECT query, to avoid having to hard-code a number.
So I'd like to avoid hardcoding:
SELECT duplicate_project(578);
And instead have something like this:
SELECT duplicate_project(SELECT project_id FROM folder WHERE name='foo' LIMIT 1);
Obviously this won't work, but is there a straightforward way to do something like it?

Do you mean something like this:
select duplicate_project(f.project_id)
from folder f
where name = 'foo'
limit 1;
The limit is not really needed. In that case you get multiple rows that would show the result of duplicate_project() for each project_id returned.
Or:
SELECT duplicate_project( (SELECT project_id FROM folder WHERE name='foo' LIMIT 1) );

One method would be a scalar subquery:
SELECT duplicate_project( (SELECT project_id FROM folder WHERE name='foo' LIMIT 1) );
Another would be to use a FROM clause:
SELECT duplicate_project(x.project_id)
FROM (SELECT project_id FROM folder WHERE name = 'foo' LIMIT 1) x;

Related

SQL Parameter to Include All on ID Column

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.

Using CONTAINS to find items IN a table

I'm trying to write a SP that will allow users to search on multiple name strings, but supports LIKE functionality. For example, the user's input might be a string 'Scorsese, Kaurismaki, Tarkovsky'. I use a split function to turn that string into a table var, with one column, as follows:
part
------
Scorsese
Kaurismaki
Tarkovsky
Then, normally I would return any values from my table matching any of these values in my table var, with an IN statement:
select * from myTable where lastName IN (select * from #myTableVar)
However, this only returns exact matches, and I need to return partial matches. I'm looking for something like this, but that would actually compile:
select * from myTable where CONTAINS(lastName, select * from #myTableVar)
I've found other questions where it's made clear that you can't combine LIKE and IN, and it's recommended to use CONTAINS. My specific question is, is it possible to combine CONTAINS with a table list of values, as above? If so, what would that syntax look like? If not, any other workarounds to achieve my goal?
I'm using SQL Server 2016, if it makes any difference.
You can use EXISTS
SELECT * FROM myTable M
WHERE
EXISTS( SELECT * FROM #myTableVar V WHERE M.lastName like '%'+ V.part +'%' )
Can your parser built the entire statement? Will that get you what you want?
select *
from myTable
where CONTAINS
(lastName,
'"Scorsese" OR "Kaurismaki" OR "Tarkovsky"'
)
This can be done using CHARINDEX function combined with EXISTS:
select *
from myTable mt
where exists(select 1 from #myTableVar
where charindex(mt.lastName, part) > 0
or charindex(part, mt.lastName) > 0)
You might want to omit one of the conditions in the inner query, but I think this is what you want.

PostgreSQL Select where multiple OR statements

I have the following PgSQL query, in which i'm looking where user_id equals any one of a set of id's i am looking for.
Question is, is there a way to simply the statement so that I dont have to keep putting user_id= ?
SELECT *
FROM comments
WHERE session_id=1
AND (user_id=10 OR user_id=11
OR user_id=12 OR user_id=13
OR user_id=14 OR user_id=15
OR user_id=16)
SELECT *
FROM comments
WHERE session_id=1
AND user_id in (10,11,12,13,14,15,16);
alternatively for this specific case:
SELECT *
FROM comments
WHERE session_id=1
AND user_id between 10 and 16;

How to give the output of the first query(which has two values) as the input to the second?

i get 2 names as the output of the first query....
eg: paul,peter
now this should be the input for the second query,
which has to display paul's and peter's email ids....
For nested queries I would strongly recommend WITH clause. It makes long complex queries order of magnitude easier to understand / construct / modify:
WITH
w_users AS( -- you can name it whatever you want
SELECT id
FROM users
WHERE < long condition here >
),
w_other_subquery AS(
...
)
SELECT email_id
FROM ...
WHERE user_id IN (SELECT id FROM w_users)
You can use like this
LIKE
SELECT USER_ID,EMAIL_ID FROM USERS where user_id IN
(SELECT PRODUCT_MEMBERS FROM PRODUCT WHERE PRODUCT_NAME='ICP/RAA');
Just use the IN clause '=' is used for matching one result
You can use In Command to get result
ex:
SELECT email FROM tableName WHERE (Name IN ('paul', 'peter'))

Is there any way to combine IN with LIKE in an SQL statement?

I am trying to find a way, if possible, to use IN and LIKE together. What I want to accomplish is putting a subquery that pulls up a list of data into an IN statement. The problem is the list of data contains wildcards. Is there any way to do this?
Just something I was curious on.
Example of data in the 2 tables
Parent table
ID Office_Code Employee_Name
1 GG234 Tom
2 GG654 Bill
3 PQ123 Chris
Second table
ID Code_Wildcard
1 GG%
2 PQ%
Clarifying note (via third-party)
Since I'm seeing several responses which don't seems to address what Ziltoid asks, I thought I try clarifying what I think he means.
In SQL, "WHERE col IN (1,2,3)" is roughly the equivalent of "WHERE col = 1 OR col = 2 OR col = 3".
He's looking for something which I'll pseudo-code as
WHERE col IN_LIKE ('A%', 'TH%E', '%C')
which would be roughly the equivalent of
WHERE col LIKE 'A%' OR col LIKE 'TH%E' OR col LIKE '%C'
The Regex answers seem to come closest; the rest seem way off the mark.
I'm not sure which database you're using, but with Oracle you could accomplish something equivalent by aliasing your subquery in the FROM clause rather than using it in an IN clause. Using your example:
select p.*
from
(select code_wildcard
from second
where id = 1) s
join parent p
on p.office_code like s.code_wildcard
In MySQL, use REGEXP:
WHERE field1 REGEXP('(value1)|(value2)|(value3)')
Same in Oracle:
WHERE REGEXP_LIKE(field1, '(value1)|(value2)|(value3)')
Do you mean somethign like:
select * FROM table where column IN (
SELECT column from table where column like '%%'
)
Really this should be written like:
SELECT * FROM table where column like '%%'
Using a sub select query is really beneficial when you have to pull records based on a set of logic that you won't want in the main query.
something like:
SELECT * FROM TableA WHERE TableA_IdColumn IN
(
SELECT TableA_IdColumn FROM TableB WHERE TableA_IDColumn like '%%'
)
update to question:
You can't combine an IN statement with a like statement:
You'll have to do three different like statements to search on the various wildcards.
You could use a LIKE statement to obtain a list of IDs and then use that in the IN statement.
But you can't directly combine IN and LIKE.
Perhaps something like this?
SELECT DISTINCT
my_column
FROM
My_Table T
INNER JOIN My_List_Of_Value V ON
T.my_column LIKE '%' + V.search_value + '%'
In this example I've used a table with the values for simplicity, but you could easily change that to a subquery. If you have a large list (like tens of thousands) then performance might be rough.
select *
from parent
where exists( select *
from second
where office_code like trim( code_wildcard ) );
Trim code_wildcard just in case it has trailing blanks.
You could do the Like part in a subquery perhaps?
Select * From TableA Where X in (Select A from TableB where B Like '%123%')
tsql has the contains statement for a full-text-search enabled table.
CONTAINS(Description, '"sea*" OR "bread*"')
If I'm reading the question correctly, we want all Parent rows that have an Office_code that matches any Code_Wildcard in the "Second" table.
In Oracle, at least, this query achieves that:
SELECT *
FROM parent, second
WHERE office_code LIKE code_wildcard;
Am I missing something?