SQL query: Where and like statments - mysql

I'm trying to make a query to get the results that have null in one of their columns but for for some reason when I use like the part where I exclude the not null fields doesnt work
SELECT * FROM my_column WHERE title LIKE "%hea%" OR department LIKE "%hea%" OR title_pt LIKE "%hea%" AND deleted_at IS NULL LIMIT 10 OFFSET 0

You need parenthesis
SELECT * FROM my_column WHERE (title LIKE "%hea%" OR department LIKE "%hea%" OR
title_pt LIKE "%hea%") AND deleted_at IS NULL LIMIT 10 OFFSET 0
Think of it like math, you have to tell it the order of operation. You were actually asking for title_py LIKE "%hea" AND deleted_at IS NULL while the other ORs were not interacting with the AND at all.

you wrote this :
SELECT * FROM my_column
WHERE (title LIKE "%hea%") OR (department LIKE "%hea%")
OR ((title_pt LIKE "%hea%") AND (deleted_at IS NULL))
LIMIT 10 OFFSET 0
You wanted this:
SELECT * FROM my_column
WHERE ((title LIKE "%hea%") OR (department LIKE "%hea%") OR (title_pt LIKE "%hea%"))
AND (deleted_at IS NULL)
LIMIT 10 OFFSET 0

The parenthesis will give you ONLY the rows with deleted_at NULL AND one of the other conditions TRUE:
SELECT *
FROM my_column
WHERE (
title LIKE "%hea%"
OR department LIKE "%hea%"
OR title_pt LIKE "%hea%"
)
AND
deleted_at IS NULL
LIMIT 10 OFFSET 0

Related

MySQL: select rows first starts with SOMETHING then containing SOMETHING

I want to select rows from tags table where tag name includes SOMETHING. The results must be sorted in a smart way: records which start with SOMETHING should go first, and then should go the rest.
It can be easily achieved using 2 queries: select by tag like 'SOMETHING%' first, and then by tag like '%SOMETHING%'. I want to combine this into one query. Is it possible? In general I want some equations which are usually used in WHERE clause to present in FIELDS section. For example,
SELECT
*,
(`name` like 'SOMETHING' ? 1 : 0) as weight0,
(`name` like 'SOMETHING%' ? 1 : 0) as weight1,
(match `name` against 'SOMETHING') as weight2,
length(name) as weight3
FROM `tags`
WHERE `name` like '%SOMETHING%'
ORDER BY weight0, weight1 desc, weight2 desc, weight3, name
LIMIT 0, 10
Obviously, the pseudo code above does not work, but I hope it shows the goal: moving WHERE conditions to SELECT area, assign numeric values, and the sort by these values. Is it somehow possible to achieve in MySQL?
You can use conditional statement like case when
SELECT
*,
(case when `name` like 'SOMETHING' then 1 else 0 end) as weight0,
(case when `name` like 'SOMETHING%' then 1 else 0 end) as weight1,
length(name) as weight3
FROM `tags`
WHERE `name` like '%SOMETHING%'
ORDER BY weight0, weight1 desc, weight3, name
LIMIT 0, 10
MySql evaluates boolean expressions as 1 for true or 0 for false and they can be used in the ORDER BY clause:
SELECT *
FROM tags
WHERE name LIKE '%SOMETHING%'
ORDER BY name = 'SOMETHING' DESC,
name LIKE 'SOMETHING%' DESC,
name LIKE '%SOMETHING%' DESC, -- this is not actually needed
CHAR_LENGTH(name),
name
LIMIT 0, 10;

how to write a query for scenario?

how to write a single query for my scenario?
I have three where conditions ?
select * (select * ,'sony' as searchItem from dg_deal_product where name like '%sony%' or
select * , 'samsung' as searchItem from where dg_deal_product where name like '%samsung%' or
select * , 'wip' as searchItem from where dg_deal_product where name like '%wip%') order by column desc,column2 desc,column3;
Just guessing here, but perhaps you are looking for something like this:
SELECT p.*
,CASE WHEN p.name LIKE '%sony%' THEN 'sony'
WHEN p.name LIKE '%samsung%' THEN 'samsung'
WHEN p.name LIKE '%wip%' THEN 'wip'
ELSE NULL
END AS searchItem
FROM dg_deal_product p
ORDER BY 1 DESC, 2 DESC, 3

mysql query where clause using AND and OR

Can someone help me with this query:
SELECT SQL_CALC_FOUND_ROWS *
FROM Punches
WHERE Serial LIKE '%123%'
OR Badge LIKE '%123%'
OR Search_Date LIKE '%123%'
OR Punch_Time LIKE '%123%'
OR Device_Name LIKE '%%'
AND Company_ID = '0002'
LIMIT 0, 20
Essentially I want to search all these fields that are LIKE 123 BUT have to have Company_ID = '0002'. This query returns rows that do not have a Company_ID = '0002'
Try this...
SELECT
SQL_CALC_FOUND_ROWS *
FROM
Punches
WHERE
(Company_ID = '0002') AND
(Serial LIKE '%123%'
OR Badge LIKE '%123%'
OR Search_Date LIKE '%123%'
OR Punch_Time LIKE '%123%'
OR Device_Name LIKE '%%')
LIMIT 0, 20
1) AND has a higher priority than OR. Just add parentheses:
SELECT SQL_CALC_FOUND_ROWS *
FROM Punches
WHERE (... OR ... OR ...)
AND Company_ID = '0002'
LIMIT 0, 20
2) Device_Name LIKE '%%' is always true.

Two LIKE conditions but retrieving from one first then the other

SELECT *
FROM address
WHERE name LIKE 'a%' OR name LIKE '% a%' LIMIT 10
This query retrieves names that start with a either at the beginning 'a%'
or in a word in the middle '% a%'. How can I retrieve results from LIKE 'a%' first
then LIKE '% a%'?.
add ORDER BY clause,
SELECT *
FROM address
WHERE name LIKE 'a%' OR name LIKE '% a%'
ORDER BY CASE WHEN name LIKE 'a%' THEN 0 ELSE 1 END
LIMIT 10
Here it is:
SELECT t1.*
FROM (
SELECT *
FROM address
WHERE name LIKE 'a%'
LIMIT 10
) t1
WHERE t1.name LIKE '% a%'
A union query may be in order here. Per MySQL documentation
To cause rows in a UNION result to consist of the sets of rows retrieved by each SELECT one after the other, select an additional column in each SELECT to use as a sort column and add an ORDER BY following the last SELECT:
(SELECT 1 AS sort_col, col1a, col1b, ... FROM t1)
UNION
(SELECT 2, col2a, col2b, ... FROM t2) ORDER BY sort_col;
So for your case something like
(Select *, 1 as sortcol from addresses where name like 'a%')
Union
(Select *, 2 as sortcol from addresses where name like '% a%')
Order by sortcol
Link: http://dev.mysql.com/doc/refman/5.0/en/union.html
One approach is to add an ORDER BY clause to your query:
ORDER BY IF(name LIKE 'a%',1,2)
Something like this:
SELECT *
FROM address
WHERE name LIKE 'a%' OR name LIKE '% a%'
ORDER BY IF(name LIKE 'a%',1,2)
LIMIT 10
To avoid a "Using filesort" operation on large sets (i.e. LOTS of rows in address), and if you only want to return 10 rows, a more complex looking query will likely perform better, by limiting the number of rows to be sorted:
SELECT c.*
FROM ( SELECT a.*
FROM (
SELECT *
FROM address
WHERE name LIKE 'a%'
LIMIT 10
) a
UNION ALL
SELECT b.*
FROM address b
WHERE b.name LIKE '% a%' AND b.name NOT LIKE 'a%'
LIMIT 10
) c
ORDER BY c.name LIKE 'a%' DESC
LIMIT 10

UNION and LIMIT 1 clarification

I have a terrible doubt.
I have a query like this:
SELECT id,fatherID FROM comments WHERE fatherID IS NULL
UNION
SELECT id,fatherID FROM comments WHERE fatherID IS NOT NULL
LIMIT 1
(Note the limit 1 applies to the union, not to only the second query)
(Note2: IS NULL, and IS NOT NULL are just an example, they can be a random string too)
With this limit 1 I am sure that this kind of query will return the row from the first query all the time?
Or even if both query returns something it can happen that the LIMIT 1 get the row coming from the second query?
I am asking this because If i run that query (wtihtou limit 1) I get this results
http://img856.imageshack.us/img856/5212/immaginejv.jpg
When I would except something like this (First all the rows with fatherid = null, then the other):
http://img847.imageshack.us/img847/479/immaginehx.jpg
Order of returned results is (by default) undefined. If you want them ordered in a specific manner, use ORDER BY, it was made to do exactly this.
I have a question regarding your query. Why you would require this query? You are nothing but selecting all rows by making union of both opposite queries i.e
fatherID IS NULL OR NOT NULL
How can duplicate rows will present in result by this union query?
SELECT id, fatherID
FROM comments
WHERE fatherID IS NULL
UNION
SELECT id, fatherID
FROM comments
WHERE fatherID IS NOT NULL
LIMIT 1
You can get result (First all the rows with fatherid = null, then the other): directly by this query:
SELECT id, fatherID
FROM comments
ORDER By fatherID
Updated answer:
SELECT *
FROM
(SELECT
id, fatherID
FROM
comments
WHERE
fatherID = 'somerandomstring1'
UNION
SELECT
id, fatherID
FROM
comments
WHERE
fatherID = 'somerandomstring2') combined_comments
ORDER BY
combined_comments.fatherID
LIMIT 1