Select if exists in part of a column - mysql

I have a table with columns. I'm storing numbers in a VARCHAR(245) column. The numbers change all the time. For example, the number can be 42 or 5 or whatever. It can also have multiple numbers, like 42,5,20 and so on.
I want to select if one of the numbers exists and not all. For example, if the numbers are 42,5,20, I want to select if the number 42 exists in the column, or select if the number 4 or the number 5 appear.
I currently have a query that will select only if there's only one number:
SELECT COUNT(*) FROM TABLE WHERE COLUMN1='42' AND COLUMN2='1';
When there are multiple numbers, the query can't find it.

You should be checking with like-wise operators with multiple checks for an exact value, for the value in between, for the value at the end and at the start.
SELECT COUNT(*) FROM TABLE WHERE (COLUMN1='42' OR COLUMN1 LIKE'%,42,%' OR COLUMN1 LIKE'%,42' OR COLUMN1 LIKE '42,%') AND COLUMN2='1';

You can use a regular expression to solve this. If you use the check for word boundaries you will avoid partial matches.
e.g.
mysql> select '42,5,20' REGEXP '[[:<:]]42[[:>:]]' AS 'Found';
+-------+
| Found |
+-------+
| 1 |
+-------+
But doesn't find a partial match
mysql> select '42,5,20' REGEXP '[[:<:]]2[[:>:]]' AS 'Found';
+-------+
| Found |
+-------+
| 0 |
+-------+
This would make your query
SELECT COUNT(*)
FROM TABLE
WHERE COLUMN1 REGEXP '[[:<:]]42[[:>:]]'
AND COLUMN2 = '1';

Related

SQL query to select columns with exact like?

Consider this SQL table
id | name | numbers
------------------------
1 | bob | 1 3 5
2 | joe | 7 2 15
This query returns the whole table as its result:
SELECT * FROM table WHERE numbers LIKE '%5%'
Is there an SQL operator so that it only returns row 1 (only columns with the number 5)?
Use regexp with word boundaries. (But you should ideally follow Gordon's comment)
where numbers REGEXP '[[:<:]]5[[:>:]]'
It's a pity that you are not using the comma as a separator in your numbers column, because it would be possible to use the FIND_IN_SET function, but you can use it together with REPLACE, like this:
SELECT * FROM table WHERE FIND_IN_SET(5, REPLACE(numbers, ' ', ','));

Explaining a SELECT statement script in detail for MySql

For one of the questions in my computing coursework, I was asked to explain the following SQL script in detail:
SELECT exam_board, COUNT(*)
FROM subjects
GROUP BY exam_board;
Below is what I have written in response to that question. I was just wondering if I forgot to include something, or if I incorrectly stated something.Any feedback at all would be greatly appreciated!
The script begins with a SELECT statement. A SELECT statement retrieves records from one or more tables or databases (, the data that is returned is then stored inside a result table, which is called a result-set). ‘COUNT ()’ is a function which returns (all (, as there is an asterisk)) the number of rows which match a specified criteria and it gives a total number of records fetched in a query. Therefore ‘SELECT exam_board, COUNT() FROM subjects’ means that the script will return all exam boards from the ‘exam_board’ column in the ‘subjects’ table with their count (of how many subjects are of that exam board). Finally the last line is ‘GROUP BY exam_board;’ the ‘GROUP BY’ clause is often used in SELECT statements to collect data from a number of records. Its purpose is to group the results in one or more columns. In this case it was grouped by ‘exam_board’, meaning that the result of the query will be grouped into a column of the exam boards.
You forgot the effect of GROUP BY is to reduce the result set to one row per distinct value in the grouping column (exam_board in this query).
So there might be 10,000 rows in the subjects table, but only four distinct values for exam_board. Using GROUP BY means you will only have four rows in the result set, exactly one row for each exam_board.
Then the COUNT(*) will be the count of rows that were "collapsed" for each respective group.
I request that you do not copy & paste my answer, but write your own answer in your own words. My writing style is pretty different from yours, so if you copy & paste, it'll be obvious to your teacher that you lifted this.
Actually this not the best answer.
SELECT can return not only data from the tables, but any result of any function, for example SELECT VERSION() returns a version of server software.
An asterisk as a parameter for COUNT(*) does not matter at all. You can put here any column or function, even COUNT(VERSION()), the result will be the same.
‘SELECT exam_board, COUNT() FROM subjects’ will return a single row with two columns: the total number of rows in table 'subjects' and the value of 'exam_board' column in the first row of the table.
Content of the table:
mysql> select exam_board from subjects;
+------------+
| exam_board |
+------------+
| 2 |
| 2 |
| 3 |
| 3 |
| 3 |
+------------+
5 rows in set (0.00 sec)
Mixing together column values and a function returning a single value like SUM(), MIN(), MAX() etc without grouping functions:
mysql> select exam_board, count(*) from subjects;
+------------+----------+
| exam_board | count(*) |
+------------+----------+
| 2 | 5 |
+------------+----------+
1 row in set (0.00 sec)
And only with grouping operator we will get the desired result: the count of records for each value of exam_board field.
mysql> select exam_board, count(*) from subjects group by exam_board;
+------------+----------+
| exam_board | count(*) |
+------------+----------+
| 2 | 2 |
| 3 | 3 |
+------------+----------+
2 rows in set (0.00 sec)

Mysql regex for numbers

I have a mysql database table with rows like this
id | values
1 | 5,6,8,1,9
2 | 12,22,5,20
3 | 18,55,3,2
I want a help in SELECT statement
To select rows that contain Numbers 1 OR 2
Without selecting rows that contain numbers like 12 or 22
SELECT * FROM test WHERE values REGEXP '/(^[,])?(1)(^[,])?/';
This is the regex you should use: (^|,)[12]($|,)
SELECT * FROM test WHERE values REGEXP '/(^|,)[12]($|,)/';

MySQL select column name and value as a field

I have a mysql table that looks something like this:
id | PO | DAP | MEDIA
---|----|-------|------
1 | 2 | 34 | 64
2 | 6 | 53 | 23
I would like to be able to query get multiple rows, one for each column. E.g:
SELECT column_name as column, column_value as value FROM my_table;
Which would give me:
PO=2,DAP=34,MEDIA=54,PO=6,DAP=53,MEDIA=23
What would I need to use to formulate a query like this?
You have to first CONCAT the data of each specified field and apply GROUP_CONCAT ON the result.
Query
SELECT GROUP_CONCAT(temp_col) FROM
(
SELECT 1 as 'temp_id',
CONCAT(
CONCAT('PO=', PO),
',',
CONCAT('DAP=', DAP),
',',
CONCAT('MEDIA=', MEDIA)
) AS 'temp_col'
FROM test
) temp
GROUP BY temp_id
Check Out SQLFIDDLE
Not exactly sure what you mean. But this is traditionally done in this manner
SELECT * FROM my_table;
You'll get your array like this
array(0=>array('PO'=>2,'DAP'=>34,'MEDIA'=54), 1=>array('PO'=>6, 'DAP'=>53, 'MEDIA'=> 23))
.. like so.

Best way to check if a row matching a condition exists at least once [duplicate]

I'm trying to find out if a row exists in a table. Using MySQL, is it better to do a query like this:
SELECT COUNT(*) AS total FROM table1 WHERE ...
and check to see if the total is non-zero or is it better to do a query like this:
SELECT * FROM table1 WHERE ... LIMIT 1
and check to see if any rows were returned?
In both queries, the WHERE clause uses an index.
You could also try EXISTS:
SELECT EXISTS(SELECT * FROM table1 WHERE ...)
and per the documentation, you can SELECT anything.
Traditionally, an EXISTS subquery starts with SELECT *, but it could
begin with SELECT 5 or SELECT column1 or anything at all. MySQL
ignores the SELECT list in such a subquery, so it makes no difference.
I have made some researches on this subject recently. The way to implement it has to be different if the field is a TEXT field, a non unique field.
I have made some tests with a TEXT field. Considering the fact that we have a table with 1M entries. 37 entries are equal to 'something':
SELECT * FROM test WHERE text LIKE '%something%' LIMIT 1 with
mysql_num_rows() : 0.039061069488525s. (FASTER)
SELECT count(*) as count FROM test WHERE text LIKE '%something% :
16.028197050095s.
SELECT EXISTS(SELECT 1 FROM test WHERE text LIKE '%something%') :
0.87045907974243s.
SELECT EXISTS(SELECT 1 FROM test WHERE text LIKE '%something%' LIMIT 1) : 0.044898986816406s.
But now, with a BIGINT PK field, only one entry is equal to '321321' :
SELECT * FROM test2 WHERE id ='321321' LIMIT 1 with
mysql_num_rows() : 0.0089840888977051s.
SELECT count(*) as count FROM test2 WHERE id ='321321' : 0.00033879280090332s.
SELECT EXISTS(SELECT 1 FROM test2 WHERE id ='321321') : 0.00023889541625977s.
SELECT EXISTS(SELECT 1 FROM test2 WHERE id ='321321' LIMIT 1) : 0.00020313262939453s. (FASTER)
A short example of #ChrisThompson's answer
Example:
mysql> SELECT * FROM table_1;
+----+--------+
| id | col1 |
+----+--------+
| 1 | foo |
| 2 | bar |
| 3 | foobar |
+----+--------+
3 rows in set (0.00 sec)
mysql> SELECT EXISTS(SELECT 1 FROM table_1 WHERE id = 1);
+--------------------------------------------+
| EXISTS(SELECT 1 FROM table_1 WHERE id = 1) |
+--------------------------------------------+
| 1 |
+--------------------------------------------+
1 row in set (0.00 sec)
mysql> SELECT EXISTS(SELECT 1 FROM table_1 WHERE id = 9);
+--------------------------------------------+
| EXISTS(SELECT 1 FROM table_1 WHERE id = 9) |
+--------------------------------------------+
| 0 |
+--------------------------------------------+
1 row in set (0.00 sec)
Using an alias:
mysql> SELECT EXISTS(SELECT 1 FROM table_1 WHERE id = 1) AS mycheck;
+---------+
| mycheck |
+---------+
| 1 |
+---------+
1 row in set (0.00 sec)
In my research, I can find the result getting on following speed.
select * from table where condition=value
(1 total, Query took 0.0052 sec)
select exists(select * from table where condition=value)
(1 total, Query took 0.0008 sec)
select count(*) from table where condition=value limit 1)
(1 total, Query took 0.0007 sec)
select exists(select * from table where condition=value limit 1)
(1 total, Query took 0.0006 sec)
I feel it is worth pointing out, although it was touched on in the comments, that in this situation:
SELECT 1 FROM my_table WHERE *indexed_condition* LIMIT 1
Is superior to:
SELECT * FROM my_table WHERE *indexed_condition* LIMIT 1
This is because the first query can be satisfied by the index, whereas the second requires a row look up (unless possibly all the table's columns are in the index used).
Adding the LIMIT clause allows the engine to stop after finding any row.
The first query should be comparable to:
SELECT EXISTS(SELECT * FROM my_table WHERE *indexed_condition*)
Which sends the same signals to the engine (1/* makes no difference here), but I'd still write the 1 to reinforce the habit when using EXISTS:
SELECT EXISTS(SELECT 1 FROM my_table WHERE *indexed_condition*)
It may make sense to add the EXISTS wrapping if you require an explicit return when no rows match.
Suggest you not to use Count because count always makes extra loads for db use SELECT 1 and it returns 1 if your record right there otherwise it returns null and you can handle it.
At times it is quite handy to get the auto increment primary key (id) of the row if it exists and 0 if it doesn't.
Here's how this can be done in a single query:
SELECT IFNULL(`id`, COUNT(*)) FROM WHERE ...
A COUNT query is faster, although maybe not noticeably, but as far as getting the desired result, both should be sufficient.
For non-InnoDB tables you could also use the information schema tables:
http://dev.mysql.com/doc/refman/5.1/en/tables-table.html
I'd go with COUNT(1). It is faster than COUNT(*) because COUNT(*) tests to see if at least one column in that row is != NULL. You don't need that, especially because you already have a condition in place (the WHERE clause). COUNT(1) instead tests the validity of 1, which is always valid and takes a lot less time to test.
Or you can insert raw sql part to conditions
so I have
'conditions'=>array('Member.id NOT IN (SELECT Membership.member_id FROM memberships AS Membership)')
COUNT(*) are optimized in MySQL, so the former query is likely to be faster, generally speaking.