full text search excluding a specific criteria - mysql

I have this table called items and I enabled full text searching on name column
id name price
---- ------ -------
1 brown wood 550
2 black wood 430
3 wooden chair 15
4 kitchen knife 3
5 sponge ball 1.35
I want to write a query to select all items whom name doesn't include 'wood' using full text search
so the result would be
id name price
---- ------ -------
4 kitchen knife 3
5 sponge ball 1.35
here is my query
SELECT * FROM items WHERE Match(name) Against('-wood' IN BOOLEAN MODE);

If you don't want wood, then the fist stab at a query would be:
SELECT *
FROM items
WHERE Match(name) Against('-wood*' IN BOOLEAN MODE);
However, the - only works after other terms are matched. So, you need some sort of positive match. Something like:
SELECT *
FROM items
WHERE Match(name) Against('k* and -wood*' IN BOOLEAN MODE);
If you know that such exclusions are common, you might include a particular word in every name (say, "name"). Alternatively, you might need to resort to like:
select *
from items i
where concat(' ', name' not like '% wood%';

Related

How to SELECT an specific value or any other in a 1-N tables relation

I would like to find a query to perform the following results, I've tried a lot of differents methods but I can't really find the proper way to do it, I would appreciate if someone can help me on this.
Keep in mind that I can have a lot of different languages and I always want to prioritize one.
Having the following tables:
item
id
info
1
Etc
2
Etc
item_translation
item_id
lang_id
value
1
1
English Translation for item 1
1
2
French translation for item 1
2
2
French translation for item 2
I would like to select all items and only one item_translation for each item prioritizing a language.
For example if I would like to select all items prioritizing language 1 it should return the following:
id
info
value
lang_id
1
Etc
English Translation for item 1
1
2
Etc
French translation for item 2
2
And if I would like to prioritize language 2:
id
info
value
lang_id
1
Etc
French translation for item 1
2
2
Etc
French translation for item 2
2
To prioritize lang_id #1 you can do:
select
i.id,
i.info,
x.value,
x.lang_id
from item i
left join (
select *,
row_number() over(partition by item_id
order by case when lang_id =
1 -- lang_id to prioritize
then 1 else 2 end) as rn
from item_translation
) x on x.item_id = i.id and x.rn = 1
Result:
id info value lang_id
--- ----- ------------------------------- -------
1 Etc English Translation for item 1 1
2 Etc French Translation for item 2 2
See running example at DB Fiddle.
It will show:
When multiple languages are available it will prioritize the preferred language.
When the preferred language is not available it will select a random other.
When no translation is available it will show nulls.

How to delete rows based on like, but but not for every like statement

I have a table in my MySQL named Animals in which the description column has the values such as
Id
description
age
1
Animal is Cat
14
2
Animal is Dog
3
3
Animal is Tiger
5
4
Animal is Bat
12
5
Animal is Rat
8
6
Animal is Squirrel
13
7
Animal is Cat
4
8
Dog
13
9
Tiger
15
I need to delete those rows which doesn't have the description values Cat, Bat and Squirrel when the description is starting with 'Animal is ' and whose age is above 12 or equal to 12
Which means, I need to only remove the rows whose description only starts with 'Animal is' but I don't want to delete it for 'Animal is cat', 'Animal is Bat', 'Animal is Squirrel'
Id
description
age
1
Animal is Cat
14
4
Animal is Bat
12
6
Animal is Squirrel
13
8
Dog
13
9
Tiger
15
I've tried doing,
DELETE FROM animals WHERE description LIKE 'Animal is%' and Age >=12;
But that seems to be removing all the rows, and I'd like to keep the values of cat, bat and Squirrel.
To select the records you want you can use these conditions:
age >= 12 AND
((description NOT LIKE 'Animal is%') OR (description LIKE '%Cat') OR
(description LIKE '%Bat') OR
(description LIKE '%Squirrel'))
So, you can delete all other rows by applying NOT to the above:
DELETE FROM animals
WHERE
NOT (
age >= 12 AND
((description NOT LIKE 'Animal is%') OR (description LIKE '%Cat') OR
(description LIKE '%Bat') OR (description LIKE '%Squirrel'))
)
Demo here
I am trying to filter the rows having the description that starts with "Animal is" and then, from those rows, I am excluding the results which are specific for cat, bat, squirrel. Note that columns like 'Animal is cat cat' or "Animal is cat bat" or "Animal is cat monkey" would be deleted as well.
DELETE FROM animals where description like 'Animal is%' and description NOT REGEXP '^Animal is Cat|Animal is Bat|Animal is Squirrel$' and age>=12;

How to select rows which have same value in some column

I have data table "menu" like this
id name type
-----------------------------
10 tea drink
20 krabby patties food
30 coffee drink
40 kelpo food
50 kelp shake drink
I want to select all id of drink, like this
id
---
10
30
50
i'm sorry, can you help me?
Select id from menu where type = 'drink';
This is a basic SQL you can simple search and find it
SELECT ID FROM menu WHERE TYPE='drink';
You can even use IN Operator
Query
SELECT id FROM menu
WHERE type in ('drink');

How to get results from Mysql database using WHERE if there is more than 1 criterion for identification?

id points year country
-----------------------------------
1 45 1998 Mexico
2 45 2000 Germany
3 47 2010 Russia
4 45 1970 China
5 49 2010 Austria
I wonder how can I take row results considering only 2 items from country column. For example only records where country is Germany and Mexico. When I try to get results where only 1 country is criterion the thing is easy:
SELECT * FROM List WHERE Country='Mexico';
the result is:
id points year country
-----------------------------------
1 45 1998 Mexico
but when I try to get results where 2 country items are criteria problems start. I tried:
SELECT * FROM List WHERE country='Mexico' AND Country='Germany';
SELECT * FROM List WHERE country='Mexico' AND 'Germany';
SELECT * FROM List WHERE country='Mexico','Germany';
SELECT * FROM List WHERE country='Mexico'AND WHERE country='Germany';
but no desired result:
id points year country
-----------------------------------
1 45 1998 Mexico
2 45 2000 Germany
I understand that maybe I committed logical error because there is no single record where country is Mexico and Germany at same time, and sql maybe understands claim exactly that way, but, how to write correctly in sql language: Give me results for records where countries are Mexico and Germany. Thanks.
You are looking for IN operator
SELECT * FROM List WHERE Country in ('Mexico','Germany');
Just use OR.
So instead of
SELECT * FROM List WHERE country='Mexico' AND Country='Germany';
it would be
SELECT * FROM List WHERE country='Mexico' OR country='Germany';
IN is also a good function to use, especially if you've got multiple values that you want to check against but that's been covered in the other answers.
You need to use or or in, you have been using and and asking mysql to find a row where country is both Mexico and Germany which is not true.
SELECT * FROM List WHERE Country in ('Mexico','Germany');
try this:
SELECT * FROM List WHERE country='Mexico' OR Country='Germany';
SQL is using logic. Natural language is not.
When you say that you want the results for a list of countries you need to specify so. This request corresponds to an logical or. Since the name can be one or the other, both are correct.
SELECT * FROM List WHERE Country = 'Mexico' OR Country = 'Germany'
To prevent further mistakes like these, I recommend that you look up logical operations in the docs (they are very good). MySQL or the PostGres, both should be fine.

How to show multiple values of a single field in a single row in a single query?

Table 1:Domain Link Result
======================================================================
||Column1(words) ||Column2(links) ||Column3(frequency) ||
======================================================================
1 1 Any Number
2 1 Any Number
3 1 Any Number
4 1 Any Number
1 2 Any Number
2 2 Any Number
3 2 Any Number
4 2 Any Number
Table 2:Sub Link Result
======================================================================
||Column1(words) ||Column2(sublinks) ||Column3(frequency) ||
======================================================================
1 a Any Number
2 b Any Number
3 c Any Number
4 d Any Number
1 e Any Number
2 f Any Number
3 g Any Number
4 h Any Number
And so on.
In the above scenario user entered 4 words and 2 domain links. Now the frequency of 4 keywords is calculated on domain links as well sublinks and stored in separate tables as shown above. I want an aggregate result like below:
Table 3:Final Result
==================================================================================
||Column1(words) ||Column2(Domain links) ||Column3(Total frequency) ||
==================================================================================
Row1: 1 1 Total of frequency in both tables
2 for word "1"
----------------------------------------------------------------------------------
Row2: 2 1 Total of frequency in both tables
2 for word "2"
----------------------------------------------------------------------------------
Row3: 3 1 Total of frequency in both tables
2 for word "3"
----------------------------------------------------------------------------------
Row4: 4 1 Total of frequency in both tables
2 for word "4"
----------------------------------------------------------------------------------
I tried the following query in MySQL:
SELECT t.`keyword`, t.`link` SUM( t.`frequency` ) AS total
FROM (
SELECT `frequency`
FROM `domain_link_result`
WHERE `keyword` = 'national'
UNION ALL
SELECT `frequency`
FROM `sub_link_result`
WHERE `keyword` = 'national'
)t GROUP BY `keyword`
But in Column 2 of the final result I get only first link instead of two links for row 1. How can I get both links or any number of links entered by user in a single row ?
Words and Links have VARCHAR as type and frequency has INT type.
If you want to collapse several rows into one and still be able to see the information, you have to use GROUP_CONCAT
http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat
This outputs the collapsed values separated by commas, i.e.: a string. In your programming language you can split this string if you need individual values.
Your query would look somehow like this
SELECT keyword, GROUP_CONCAT(links), SUM(frequency)
FROM (subquery)
GROUP BY keyword
Which would output something like this:
==================================================================================
||Column1(words) ||Column2(Domain links) ||Column3(Total frequency) ||
==================================================================================
Row1: 1 1,2 sum of freq.
----------------------------------------------------------------------------------
Row2: 2 1,2 sum of freq.
----------------------------------------------------------------------------------
Row3: 3 1,2 sum of freq.
----------------------------------------------------------------------------------
Row4: 4 1,2 sum of freq.
EDIT: Extra help for your query
Your query looks a little bit confusing to me. Try with a JOIN approach:
SELECT domain_link_results.word AS word,
GROUP_CONCAT(domain_link_results.links) AS domain_links,
domain_link_results.frequency + sub_link_results.frequency AS total_frequency
FROM domain_link_results
INNER JOIN sub_link_results
ON domain_link_results.word = sub_link_results.word
WHERE domain_link_results.word = "national"
GROUP BY domain_link_results.word
On the other hand, it might be better to have all the links in the same table, and an extra field to determine if it's a domain link or a sublink. Without knowing more about your system it is hard to say.