Select from any of multiple values from a Postgres field - postgresql

I've got a table that resembles the following:
WORD WEIGHT WORDTYPE
a 0.3 common
the 0.3 common
gray 1.2 colors
steeple 2 object
I need to pull the weights for several different words out of the database at once. I could do:
SELECT * FROM word_weight WHERE WORD = 'a' OR WORD = 'steeple' OR WORD='the';
but it feels ugly and the code to generate the query is obnoxious. I'm hoping that there's a way I can do something like (pseudocode):
SELECT * FROM word_weight WHERE WORD = 'a','the';

You are describing the functionality of the in clause.
select * from word_weight where word in ('a', 'steeple', 'the');

If you want to pass the whole list in a single parameter, use array datatype:
SELECT *
FROM word_weight
WHERE word = ANY('{a,steeple,the}'); -- or ANY('{a,steeple,the}'::TEXT[]) to make explicit array conversion

If you are not sure about the value and even not sure whether the field will be an empty string or even null then,
.where("column_1 ILIKE ANY(ARRAY['','%abc%','%xyz%']) OR column_1 IS NULL")
Above query will cover all possibility.

Related

Parameterizing a query with a varying amount of WHERE clause conditionals

Let's imagine we have a table containing columns for 'color' and for 'size'. I have a list with color-size combinations (e.g. [(red, small), (blue, medium)]), of which the length is unknown. The table should be filtered based on this list, so that the result contains only the rows where the combinations apply.
A query based on the example would look like this:
SELECT * FROM items WHERE ((color = 'red' AND size = 'small') OR (color = 'blue' and size = 'medium'));
Parameterizing this query wouldn't work of course, since the amount of combinations varies.
Is there a way to achieve this using the parameterized queries like the ones that are use in node-postgres? The only solution I can think of is using string interpolation, which doesn't appear to be a safe.
It looks like good scenario for IN operator
select * from items where
(color, size) in (('red','small'), ('blue','medium'))
and it can be parametrized using arrays
select * from items where
(color, size) in (
select unnest (array['red','blue']), unnest(array['small','medium']))
First array is for colors, second for sizes. Unnest in one select create pairs.Arrays should have the same number of elements.
And arrays can be passed as parameters to query.

it is possible to concatenate one result set onto another in a single query?

I have a table of Verticals which have names, except one of them is called 'Other'. My task is to return a list of all Verticals, sorted in alpha order, except with 'Other' at the end. I have done it with two queries, like this:
String sqlMost = "SELECT * from core.verticals WHERE name != 'Other' order by name";
String sqlOther = "SELECT * from core.verticals WHERE name = 'Other'";
and then appended the second result in my code. Is there a way to do this in a single query, without modifying the table? I tried using UNION
(select * from core.verticals where name != 'Other' order by name)
UNION (select * from core.verticals where name = 'Other');
but the result was not ordered at all. I don't think the second query is going to hurt my execution time all that much, but I'm kind of curious if nothing else.
UNION ALL is the usual way to request a simple concatenation; without ALL an implicit DISTINCT is applied to the combined results, which often causes a sort. However, UNION ALL isn't required to preserve the order of the individual sub-results as a simple concatenation would; you'd need to ORDER the overall UNION ALL expression to lock down the order.
Another option would be to compute an integer order-override column like CASE WHEN name = 'Other' THEN 2 ELSE 1 END, and ORDER BY that column followed by name, avoiding the UNION entirely.

Is it possible to combine the ANY and BETWEEN operator

I need to check if any value in a Postgres array is between a given range. Something like this:
SELECT * FROM my_table WHERE ANY(my_array) BETWEEN 50 AND 60;
I realize that I can't actually do this, since the ANY operator must always be on the right side of the expression. Does anyone know of a convenient work around for doing something like this?
You can use range types, specifically the range membership operator #>:
SELECT * FROM my_table WHERE '[50,60]'::int4range #> ANY(my_array);
If you need to pull the range bounds from a column or parameter, the range constructor function might suit you better:
SELECT * FROM my_table WHERE int4range(a,b,'[]') #> ANY(my_array);
if you need range
select array_agg(q.arr) arr
from (
select unnest(ARRAY[1,2,3,4,5,6,7,8,9,10]) arr
) q
where q.arr between 3 and 5

select first letter of different columns in oracle

I want a query which will return a combination of characters and number
Example:
Table name - emp
Columns required - fname,lname,code
If fname=abc and lname=pqr and the row is very first of the table then result should be code = ap001.
For next row it should be like this:
Fname = efg, lname = rst
Code = er002 and likewise.
I know that we can use substr to retrieve first letter of a colume but I don't know how to use it to do with two columns and how to concatenate.
OK. You know you can use substr function. Now, to concatenate you will need a concatenation operator ||. To get the number of row retrieved by your query, you need the rownum pseudocolumn. Perhaps you will also need to use to_char function to format the number. About all those functions and operators you can read in SQL reference. Anyway I think you need something like this (I didn't check it):
select substr(fname, 1, 1) || substr(lname, 1, 1) || to_char(rownum, 'fm009') code
from emp

Complex SphinxQL Query

I'm trying to write a SphinxQL query that would replicate the following MySQL in a Sphinx RT index:
SELECT id FROM table WHERE colA LIKE 'valA' AND (colB = valB OR colC = valC OR ... colX = valX ... OR colY LIKE 'valY' .. OR colZ LIKE 'valZ')
As you can see I'm trying to get all the rows where one string column matches a certain value, AND matches any one of a list of values, which mixes and matches string and integer columns / values)
This is what I've gotten so far in SphinxQL:
SELECT id, (intColA = intValA OR intColB = intValB ...) as intCheck FROM rt_index WHERE MATCH('#requiredMatch = requiredValue');
The problem I'm running into is in matching all of the potential optional string values. The best possible query (if multiple MATCH statements were allowed and they were allowed as expressions) would be something like
SELECT id, (intColA = intValA OR MATCH('#checkColA valA|valB') OR ...) as optionalMatches FROM rt_index WHERE optionalMatches = 1 AND MATCH('#requireCol requiredVal')
I can see a potential way to do this with CRC32 string conversions and MVA attributes but these aren't supported with RT Indexes and I REALLY would prefer not switch from them.
One way would be to simply convert all your columns to normal fields. Then you can put all this logic inside the MATCH(..). Ie not using attributes.
Yes you can only have one MATCH per query.
Otherwise, yes you could use the CRC trick to make string attributes into integer ones, so can use for filtering.
Not sure why you would need MVA, but they are now supported in RT indexes in 2.0.2