MySQL: show strings in result that were not found - mysql

I have a MySQL db table with a column containing strings. And I have a list of strings. Some of the strings from the list can be found in my table, others can't. See my table TableName:
<TableName>
IntegerColumn, StringColumn
1, one
2, two
3, three
4, four
If I execute the query
SELECT * FROM TableName WHERE StringColumn NOT IN ('three', 'four', 'five', 'six');
I get a result of two rows, which contain nothing but NULL.
How can I see for which of the strings there was no match? Because I want to add them to the db table
Thx in advance

Using the following sample
CREATE TABLE sample_table
(
id int auto_increment primary key,
details varchar(30)
);
INSERT INTO sample_table
(id, details)
VALUES
(1, 'One'),
(2, 'Two'),
(3, 'Three'),
(4, 'Four'),
(5, 'Five');
I ran the query
SELECT * FROM sample_table
WHERE details NOT IN ('two', 'three', 'nine');
which gave the correct output of:
1 One
4 Four
5 Five
If you've got NULL returned then there is something you're not explaining in your question. Can you provide schema information or even a SQL Fiddle and I'm sure you'll get a much better answer.

I think what you want is, 'three', 'four', 'five', 'six' if any of this string is not present in the database you want to identify that.
Using query I think it will be tough. You can just use below query to get the available strings and the counts. Then, if you are using a programming language you can identify which string are not present in the result and then proceed further.
SELECT StringColumn, count(*) FROM TableName group by StringColumn
Not sure if this is what you are looking for.

This should not go this way. Check the following demo to ensure that your code is correct. Now what really matters is the set of data present in the table.
DEMO
Here is the DDL:
create table tab1 (IntegerColumn int(2), StringColumn varchar(20));
insert into tab1 values(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four');

Related

Filter Data in Sql

I have a table in which i want to get data on basis of attribute_id and attribute value pair.I want to pass array of both attribute_ids and its corresponding attribute_values and on basis of that i want to have a sku.There can be different values for same attribute id for same service_id but sku is different.Please suggest me some query.
You can select based on pairs:
SELECT `sku` FROM `mytable` WHERE (`attribute_id`, `attribute_value`) IN (
(3, 6000),
(8, 5000),
(9, 6)
);
Here's a question that offers more insight on that, as well as some more index-friendly alternatives: MySQL: How to bulk SELECT rows with multiple pairs in WHERE clause

How do I Use Wildcard (%) to Search but not include spaces?

I have a list of comma separated tags in a column in my database. I was using a simple wildcard to pull items that matches a tag that I was searching for. However, I have discovered that some tags are included as part of a title for other tags and that they are being returned also. For example, searching for hunting these rows might be returned:
hunting, fishing, outdoors <-- Should be returned
sporting goods, hunting <-- Should be returned
bargain hunting, sale <-- Should NOT be returned
bullets, guns, hunting <-- Should be returned
Currently I am using:
WHERE column LIKE '%hunting%'
What should I do to make this work more appropriately with these comma seperated lists. Also, please bear in mind that some rows may have only one tag and hence have no commas at all. Thanks.
Without using regular expressions:
WHERE column LIKE '%, hunting'
OR column LIKE '%, hunting,%'
OR column LIKE 'hunting, %'
See a demo
The solution here is to normalize your table.
CREATE TABLE products
(`id` int, `name` varchar(4));
INSERT INTO products
(`id`, `name`)
VALUES
(1, 'gun'),
(2, 'fish');
CREATE TABLE keywords
(`id` int, `keyword` varchar(15));
INSERT INTO keywords
(`id`, `keyword`)
VALUES
(1, 'hunting'),
(2, 'fishing'),
(3, 'outdoors'),
(4, 'sporting goods'),
(5, 'bargain hunting'),
(6, 'sale'),
(7, 'bullets'),
(8, 'guns');
CREATE TABLE productKeywords
(`productId` int, `keywordId` int);
INSERT INTO productKeywords
(`productId`, `keywordId`)
VALUES
(1, 1),
(1, 3),
(1, 4),
(2, 2),
(2, 5);
select * from Table1
where find_in_set('hunting',`text`)
or find_in_set(' hunting',`text`)
SAMPLE FIDDLE
Use RLIKE with the appropriate regex:
WHERE column RLIKE '(^|, )hunting(,|$)'
See an SQLFiddle live demo of this condition working correctly with the sample input from the question.

MySQL string search between commas

My db is built as follows:
value1,value2,value3 | 1
value4,value5,val"u6 | 2
value 5, value 6, value 8 |3
(Two columns, one with a key separated by commas and the other just a normal var-char)
I'm looking for the most reliable way to find a query within the quotes and I'm getting kinda lost here.
I'm using the word boundaries for that:
SELECT * FROM ABC WHERE content REGEXP '[[:<:]]value 5[[:>:]]'
The problem is when I'm doing this query:
SELECT * FROM ABC WHERE content REGEXP '[[:<:]]5[[:>:]]'
It will also return the value, which is not what I'm looking for. Another problem is that the word boundaries refer to quotes as a word boundary
How can I solve this and create a simple query that will only fetch the exact full query between the quotes?
BTW
I don't have an option to change the DB structure...
As #MarcB commented, you really should try to normalise your schema:
CREATE TABLE ABC_values (
id INT,
content VARCHAR(10),
FOREIGN KEY (id) REFERENCES ABC (id)
);
INSERT INTO ABC_values
(id, content)
VALUES
(1, 'value1'), (1, 'value2'), (1, 'value3'),
(2, 'value4'), (2, 'value5'), (2, 'val"u6'),
(3, 'value 5'), (3, 'value 6'), (3, 'value 8')
;
ALTER TABLE ABC DROP content;
Then, as required, you can perform a SQL join between your tables and group the results:
SELECT id, GROUP_CONCAT(ABC_values.content) AS content
FROM ABC LEFT JOIN ABC_values USING (id) NATURAL JOIN (
SELECT id FROM ABC_values WHERE content = 'value 5'
) t
GROUP BY id
If it is completely impossible to change the schema, you can try FIND_IN_SET():
SELECT * FROM ABC WHERE FIND_IN_SET('value 5', content)
Another workaround is to use LIKE with the delimiters of the items in your list:
WHERE content LIKE ',5,'
But the item you're looking for may be at the start or end of the list. So you have to modify the list on the fly to include the delimiters at the start and end.
WHERE CONCAT(',', content, ',') LIKE '%,5,%' -> this works for me on mysql
This works, and in some sense it's no worse than any other search that you do for an item in a comma-separated list. That's because such a search is bound to do a table-scan and therefore it's very inefficient. As the data in your table grows, you'll find it can't perform well enough to be useful.
See also my answer to Is storing a delimited list in a database column really that bad?

MYSQL CASE THEN statement with multiple values

I am trying go select multiple values with CASE statement. I noticed we cannot do
CASE
WHEN wall.type="bk"
THEN books.id1,books.id2, // and so on
END as column_1,
Is there a way to do THEN with multiple columns or do we need to simply write a bunch of CASE THEN statements? that seems messy
No, it is just a single value. Additionally, it is contradictory to use "multiple columns" and name those multiple columns as column_1, right? :)
You can use another column to store the other id with (a similar case) and use nulls to represent the else values, just like you're doing now.
Example:
CASE
WHEN wall.type="bk"
THEN books.id1
END as column_1,
CASE
WHEN wall.type="bk"
THEN books.id2
END as column_2
Check the official documentation for more information.
No. CASE statement can only return a single value, so the only way to achieve what you want is duplicate the case ...
The database server should be optimized and perform only one time the check on the same condition ...
And everything can be done, but it always depends on what you want to do. Below I'll show you a working example right after you have to take the data as an array and do what you want.
CREATE TABLE wall (`ident` int,`type` varchar(2), `order` int);
INSERT INTO wall (`ident`, `type`, `order`) VALUES
(40,'bk', 1),
(41,'bk', 5),
(42,'rt', 2),
(43,'bk', 3),
(44,'rt', 1);
CREATE TABLE books (`ident` int,`id1` int, `time` varchar(8), `id2` int);
INSERT INTO books (`ident`, `id1`, `time`, `id2`) VALUES
(40, 10, '18:07:00', 20),
(43, 11, '05:00:00', 21),
(44, 12, '21:01:00', 22),
(41, 13, '10:00:00', 23),
(42, 14, '23:10:00', 24);
#--------------------------
SELECT
CASE
WHEN wall.type='bk'
THEN CONCAT(books.id1,'-',books.id2)
END AS column_1
FROM wall JOIN books ON books.ident = wall.ident GROUP BY wall.ident ORDER BY wall.ident ASC;
Print:
column_1
1 10-20
2 13-23
3 NULL
4 11-21
5 NULL
Solution in action via this link:
http://rextester.com/LHPI38373
According to documentation mysql_doc; you can use you can use the other syntax of case for what you wanted.
case
WHEN FIND_IN_SET(edu, "1,1st,2,2nd,3,3rd,4,4th,5,5th,pri,primary,primery") THEN
SET memEdu = "Primary";
WHEN FIND_IN_SET(edu, "intermediate,inter,f.a,fa,fac,f.a.c,f.sc,fsc,1rd year,2rd year,3rd year") THEN
SET memEdu = "Intermediate";
End case;

Copy multiple records using foreign keys

Suppose I have two tabels, A and B, each with three columns (A.id, A.title, A.text and B.id, B.a_id, B.text). B.a_id is a foreign key to relates to A.id. Now, suppose there is one record in A (1, 'foo', 'bar') and 2 records in B (1, 1, 'test') and (2, 1, 'test1').
My question is, is there a standard method of copying the record in A, and, at the same time copying all the records from B that relate to A. So suppose I create a new record in A (2, 'foo', 'bar') that's based on (1, 'foo', 'bar'), is there some sort of method that creates two new records in B (3, 2, 'test') and (4, 2, 'test1)?
I've never used triggers before, is this the correct moment to start doing that? Or is this a very stupid question?
this is not a stupid question. However, I believe that this is not possible with pure SQL, or only with some exotic syntax that I am not aware of. Copying rows is not the problem (assuming that id is auto_increment):
insert into A (title, text) select title, text from A where id = XY
However, then you need to find the last insert ID to duplicate the records in B. Let's see:
insert into B (a_id, text) select LAST_INSERT_ID(), text from B where a_id = XY
Hm... maybe this works, but I am a bit sceptical about the LAST_INSERT_ID(). Anyway, I don't think it can be done with just one statement.
Let me know how it goes
Tom