How to combine LIKE and CASE WHEN in SQLite? - sql

...Hi, a database ingenue here. I'm trying to figure out how to use LIKE with CASE in SQLite, or some equivalent approach. I've got a prod_names table that contains concatenated data--occasionally just 1 item, but usually containing several comma-separated items. For my new 'Toy' column, I need to find every record that contains 'CapGun'. The code below works only when 'CapGun' is the only item, and not when there are multiple items (eg, 'BarbieDoll, CapGun, EasyBakeOven').
SELECT
customer_id,
prod_names,
CASE prod_names WHEN 'CapGun' THEN 'CG' ELSE 'not_CG' END Toy
FROM
Toys_table
ORDER BY
Toy
I've tried various approaches like WHEN LIKE '%CapGun%', WHEN INSTR(prod_names,'CapGun') > 0, and WHEN GLOB '*CapGun*' but they all return no results or throw a syntax error.
Any suggestions? I'm sure there must be a simple solution.

Use the expanded case syntax:
CASE
WHEN prod_names LIKE '%CapGun%' THEN ...
ELSE ...
END
This lets use any expression as the condition in your CASE, including other columns.

Related

SQL query with CASE WHEN used in WP_query wordpress function

I have this SQL query: SELECT * FROM `wpgo_postmeta` WHERE `meta_key` = 'price' ORDER BY CASE WHEN meta_value REGEXP '^[0-9]+$' THEN 1 ELSE 0 END, meta*value+0 DESC; *that works for me but I need to convert it so it's used by the wordpress apply_filters function.
I have tried multiple things including this WordPress Query: ORDER BY CASE WHEN
But then it returns an empty list. I know the query works because I have tested it manually.
I also tried this and it looks like it should work, but I get an empty list as well.
$query_args['meta_key'] = 'fave_property_price';
$query_args['orderby'] = "CASE WHEN meta_value REGEXP '^[0-9]+$' THEN 1 ELSE 0 END, metavalue+0 DESC;";
It looks like you want your numeric meta_value results to appear after the non-numeric ones.
In SQL you can simplify your ORDER BY like this.
ORDER BY (meta_value REGEXP '^[0-9]+$'), meta_value DESC
It works because the output of Boolean comparison operations appear a 1 for true and 0 for false.The parentheses aren't strictly necessary but they make the code a bit easier to read.
But, you cannot just stuff this SQL style clause into a WP_Query() object. Replacing the ORDER BY clause is tricky.
Start by converting this into a WP_Query operation. Those things don't look a whole lot like pure SQL. You need something like this, not debugged.
$q = new WP_Query (
['meta_key' => 'price',
'order' => 'DESC',
'orderby' => 'meta_value_num',
]);
Then you'll get your posts in numeric order by price, with oddball results for non-numeric prices. Run this query and convince yourself you get the posts you want, even if not in the perfect order.
Only then, put a filter handler on the posts_orderby filter to put in your SQLish custom ordering clause. The post you referenced shows how to do that: WordPress Query: ORDER BY CASE WHEN
Use John Blackbourn's Query Monitor plugin to see what your query looks like in real life, after all the WP_Query code finishes assembling it. The correct use of query filters can sometimes be confusing.
If code is poetry then the WP_Query code is an occult spell invocation chant. Sigh.

How to add one more column in the select using Laravel Eloquent

I am trying to use Laravel Eloquent to make a query. I would like to group the results by the level column, count the results in a total alias, and finally, bring me the id of each result. What am I doing wrong?
$fodas = Foda::groupBy('level')
->select('level', DB::raw('count (*) as total'))
->get();
The result is a collection that only brings me the level and total fields.
You'll see this pattern with many laravel facades. If you are handling 'one of something', in this case a column, you pass a string and if you are handling many of something, you pass an array.
That's why * and level are both valid. Because * is recognized a column and is expanded inside mysql to match every column.
And that's also why it doesn't work when you try to query for 'level, column2, column3' because this string is not a valid column name, so you have to pass an array with all the columns you want to use.
$fodas = Foda::groupBy('level')
->select(['level','other','column'], DB::raw('count (*) as total'))
->get();
As I said before, this applies to many laravel facades:
Facade::function('one_thing');
//or
Facade::function(['thing1','thing2','thing3']);
//or even this, for some cases
Facade::function('thing1','thing2','thing3');

SQL full text search behavior on numeric values

I have a table with about 200 million records. One of the columns is defined as varchar(100) and it's included in a full text index. Most of the values are numeric. Only few are not numeric.
The problem is that it's not working well. For example if a row contains the value '123456789' and i look for '567', it's not returning this row. It will only return rows where the value is exactly '567'.
What am I doing wrong?
sql server 2012.
Thanks.
Full text search doesn't support leading wildcards
In my setup, these return the same
SELECT *
FROM [dbo].[somelogtable]
where CONTAINS (logmessage, N'28400')
SELECT *
FROM [dbo].[somelogtable]
where CONTAINS (logmessage, N'"2840*"')
This gives zero rows
SELECT *
FROM [dbo].[somelogtable]
where CONTAINS (logmessage, N'"*840*"')
You'll have to use LIKE or some fancy trigram approach
The problem is probably that you are using a wrong tool since Full-text queries perform linguistic searches and it seems like you want to use simple "like" condition.
If you want to get a solution to your needs then you can post DDL+DML+'desired result'
You can do this:
....your_query.... LIKE '567%' ;
This will return all the rows that have a number 567 in the beginning, end or in between somewhere.
99% You're missing % after and before the string you search in the LIKE clause.
es:
SELECT * FROM t WHERE att LIKE '66'
is the same as as using WHERE att = '66'
if you write:
SELECT * FROM t WHERE att LIKE '%66%'
will return you all the lines containing 2 'sixes' one after other

SQL Query for finding a column name where matching text is in column

This is my first stakoverflow question, although I've lurked for quite a while. I'm writing a webapp in PHP/SQLite, and I'm trying to find a column name along with the following SQL query:
SELECT lexemeid FROM lexeme, sense WHERE lexeme.lexemeid =
sense.senselexemeid AND (lexeme.lexeme LIKE '%apani%' OR lexeme.variant
LIKE '%apani%' OR lexeme.affixedform LIKE '%apani%' OR sense.example
LIKE '%apani%');
Basically, I'm offering a full text lookup for a few different fields. The query above works, but I'd like to get the name of the column where my wildcard matches for each result as well. Basically I want something like the above query with the SELECT looking more like:
SELECT lexemeid, COLUMN NAME FROM...
I'd also welcome any ideas for making my SQL Query look/perform better (maybe using LIKE and IN??). I'm basically trying to join lexeme.lexemeid and sense.senselexemeid and do a wildcard lookup on a text string (in this case, "apani").
Thanks!
Assuming you only have a match in one of the columns, you could use a CASE statement.
SELECT lexemeid,
CASE WHEN lexeme.lexeme LIKE '%apani%' THEN 'lexeme'
WHEN lexeme.variant LIKE '%apani%' THEN 'variant'
...
WHEN sense.example LIKE '%apani%' THEN 'example'
END AS ColumnName
FROM ...

Searching a column containing CSV data in a MySQL table for existence of input values

I have a table say, ITEM, in MySQL that stores data as follows:
ID FEATURES
--------------------
1 AB,CD,EF,XY
2 PQ,AC,A3,B3
3 AB,CDE
4 AB1,BC3
--------------------
As an input, I will get a CSV string, something like "AB,PQ". I want to get the records that contain AB or PQ. I realized that we've to write a MySQL function to achieve this. So, if we have this magical function MATCH_ANY defined in MySQL that does this, I would then simply execute an SQL as follows:
select * from ITEM where MATCH_ANY(FEAURES, "AB,PQ") = 0
The above query would return the records 1, 2 and 3.
But I'm running into all sorts of problems while implementing this function as I realized that MySQL doesn't support arrays and there's no simple way to split strings based on a delimiter.
Remodeling the table is the last option for me as it involves lot of issues.
I might also want to execute queries containing multiple MATCH_ANY functions such as:
select * from ITEM where MATCH_ANY(FEATURES, "AB,PQ") = 0 and MATCH_ANY(FEATURES, "CDE")
In the above case, we would get an intersection of records (1, 2, 3) and (3) which would be just 3.
Any help is deeply appreciated.
Thanks
First of all, the database should of course not contain comma separated values, but you are hopefully aware of this already. If the table was normalised, you could easily get the items using a query like:
select distinct i.Itemid
from Item i
inner join ItemFeature f on f.ItemId = i.ItemId
where f.Feature in ('AB', 'PQ')
You can match the strings in the comma separated values, but it's not very efficient:
select Id
from Item
where
instr(concat(',', Features, ','), ',AB,') <> 0 or
instr(concat(',', Features, ','), ',PQ,') <> 0
For all you REGEXP lovers out there, I thought I would add this as a solution:
SELECT * FROM ITEM WHERE FEATURES REGEXP '[[:<:]]AB|PQ[[:>:]]';
and for case sensitivity:
SELECT * FROM ITEM WHERE FEATURES REGEXP BINARY '[[:<:]]AB|PQ[[:>:]]';
For the second query:
SELECT * FROM ITEM WHERE FEATURES REGEXP '[[:<:]]AB|PQ[[:>:]]' AND FEATURES REGEXP '[[:<:]]CDE[[:>:]];
Cheers!
select *
from ITEM where
where CONCAT(',',FEAURES,',') LIKE '%,AB,%'
or CONCAT(',',FEAURES,',') LIKE '%,PQ,%'
or create a custom function to do your MATCH_ANY
Alternatively, consider using RLIKE()
select *
from ITEM
where ','+FEATURES+',' RLIKE ',AB,|,PQ,';
Just a thought:
Does it have to be done in SQL? This is the kind of thing you might normally expect to write in PHP or Python or whatever language you're using to interface with the database.
This approach means you can build your query string using whatever complex logic you need and then just submit a vanilla SQL query, rather than trying to build a procedure in SQL.
Ben