mysql Like ambiguios result - mysql

I have two tables a and b.
Table a has a field named gr which can have multiple values concatained with string.
Table b holds it seperately in fields lg.
How do i run the below query to check whether b.lg is in a.gr?
now b.lg has values me,me01,me02 and a.gr has to be checked agianst me02.
But the error here is that the three as matched with this
SELECT lg
FROM a, b
WHERE a.id = 22 AND
a.gr LIKE CONCAT('%', b.lg, '%');
a.gr example values
'm301,you,weall'
'me,you,me2'
'me'
b.lg value
1.'m301'
2.'you'
3.'weall'
4.'me2'
5.'me'
6.'me1'

You can use the LOCATE or FIND_IN_SET functions. LOCATE will find partial matches; for example it will find a match for me in me1,me2. If this is not what you want, maybe you are looking for FIND_IN_SET.
SELECT lg
FROM a, b
WHERE a.id = 22 AND
LOCATE(b.lg, a.gr) > 0;
Replicating the data you have posted this is the output from the SELECT:
mysql> create temporary table a (gr varchar(100));
Query OK, 0 rows affected (0.36 sec)
mysql> create temporary table b (lg varchar(100));
Query OK, 0 rows affected (0.08 sec)
mysql> insert into a values ('m301,you,weall'),('me,you,me2'),('me');
Query OK, 3 rows affected (0.11 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> insert into b values ('m301'),('you'),('weall'),('me2'),('me'),('me1');
Query OK, 6 rows affected (0.06 sec)
Records: 6 Duplicates: 0 Warnings: 0
mysql> SELECT lg, gr FROM a, b WHERE locate(lg,gr) > 0;
+-------+----------------+
| lg | gr |
+-------+----------------+
| m301 | m301,you,weall |
| you | m301,you,weall |
| you | me,you,me2 |
| weall | m301,you,weall |
| me2 | me,you,me2 |
| me | me,you,me2 |
| me | me |
+-------+----------------+
7 rows in set (0.02 sec)

I recommend using the FIND_IN_SET() function to join the two tables.
Try something like this:
select b.lg
from a
inner join b on find_in_set(b.lg,a.gr) > 0
where a.id = 22;

Related

Use of UNION when creating tables

Database-1
create table sample (
id INT,
nm VARCHAR(10)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
UNION=(for tables from another databases);
So, when we do union what actually it meance?
Please explain, I am getting confusing for this type of UNION.
That looks close to the syntax for creating a merge table, but it has the engine type wrong. Your statement will ignore the union clause and simply create a new, empty table. In order to create merge table you need to specify ENGINE=MERGE.
14.3 The MERGE Storage Engine
The MERGE storage engine, also known as the MRG_MyISAM engine, is a
collection of identical MyISAM tables that can be used as one.
The tables you specify in the UNION clause there, must all be identical - ie, having the same index and column specification, and they must all be in the same order in each table.
After that, can you query your merge table and access the data from all of the tables that form it.
You can also insert into your merge table, which is something you cannot do with a view:
You can optionally specify an INSERT_METHOD option to control how
inserts into the MERGE table take place. Use a value of FIRST or LAST
to cause inserts to be made in the first or last underlying table,
respectively. If you specify no INSERT_METHOD option or if you specify
it with a value of NO, inserts into the MERGE table are not permitted
and attempts to do so result in an error.
Anyway, the doco has the rest of the information if you want to peruse more - I've never felt the need to use this type of table.
Example:
mysql>
mysql> create table t2 (
-> id integer primary key auto_increment,
-> val char(20)
-> ) engine=myisam;
Query OK, 0 rows affected (0.05 sec)
mysql>
mysql> insert into t1(val) values ('table1 a'), ('table1 b');
Query OK, 2 rows affected (0.01 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> insert into t2(val) values ('table2 a'), ('table2 b');
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql>
mysql>
mysql> create table mt (
-> id integer primary key auto_increment,
-> val char(20)
-> ) engine=merge union=(t1,t2) insert_method=last;
Query OK, 0 rows affected (0.04 sec)
mysql>
mysql> select * from mt;
+----+----------+
| id | val |
+----+----------+
| 1 | table1 a |
| 2 | table1 b |
| 1 | table2 a |
| 2 | table2 b |
+----+----------+
4 rows in set (0.00 sec)
mysql> insert into mt(val) values ('12345');
Query OK, 1 row affected (0.00 sec)
mysql> select * from mt;
+----+----------+
| id | val |
+----+----------+
| 1 | table1 a |
| 2 | table1 b |
| 1 | table2 a |
| 2 | table2 b |
| 3 | 12345 |
+----+----------+
5 rows in set (0.01 sec)
mysql> select * from t2;
+----+----------+
| id | val |
+----+----------+
| 1 | table2 a |
| 2 | table2 b |
| 3 | 12345 |
+----+----------+
3 rows in set (0.00 sec)

How do I roll up multiple detail rows' columns into a single column?

I have two tables:
table_a:
ID | NAME
===============
1 | DAN
2 | RON
3 | JANE
table_b:
ID | TEXT
===============
2 | APPLE
2 | BANANA
2 | COFFEE
I need to get the results for ID 2.
I was thinking that even if I got a string containing the TEXT's values for ID 2 from table_b would be great for example:
ID | NAME | TEXT
=============================
2 | RON | APPLE,BANANA,COFFEE
Is this even possible?
SELECT
A.*,GROUP_CONCAT(B.`TEXT`) `TEXT`
FROM
table_a A INNER JOIN table_b B USING (ID)
WHERE A.ID=2;
Here is a sample
mysql> DROP TABLE IF EXISTS table_a;
Query OK, 0 rows affected (0.03 sec)
mysql> DROP TABLE IF EXISTS table_b;
Query OK, 0 rows affected (0.03 sec)
mysql> CREATE TABLE table_a
-> (ID int not null auto_increment,
-> NAME VARCHAR(20),primary key (ID));
Query OK, 0 rows affected (0.13 sec)
mysql> CREATE TABLE table_b
-> (ID int not null,`TEXT` TEXT,key (ID));
Query OK, 0 rows affected (0.06 sec)
mysql> INSERT INTO table_a (NAME) VALUES ('DAN'),('RON'),('JANE');
Query OK, 3 rows affected (0.06 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> INSERT INTO table_b (ID,`TEXT`) VALUES
-> (2,'APPLE'),(2,'BANANA'),(2,'COFFEE');
Query OK, 3 rows affected (0.05 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> SELECT A.*,GROUP_CONCAT(B.`TEXT`) `TEXT`
-> FROM table_a A INNER JOIN table_b B USING (ID) WHERE A.ID=2;
+----+------+---------------------+
| ID | NAME | TEXT |
+----+------+---------------------+
| 2 | RON | APPLE,BANANA,COFFEE |
+----+------+---------------------+
1 row in set (0.00 sec)
Give it a Try !!!
To get all values available in table_a and anything that can be grouped from table_b:
SELECT
A.*,IFNULL(GROUP_CONCAT(B.`TEXT`),'') `TEXT`
FROM
table_a A LEFT JOIN table_b B USING (ID)
GROUP BY A.ID
Here is that sample:
mysql> use test
Database changed
mysql> DROP TABLE IF EXISTS table_a;
Query OK, 0 rows affected (0.03 sec)
mysql> DROP TABLE IF EXISTS table_b;
Query OK, 0 rows affected (0.02 sec)
mysql> CREATE TABLE table_a (ID int not null auto_increment,NAME VARCHAR(20),primary key (ID));
Query OK, 0 rows affected (0.01 sec)
mysql> CREATE TABLE table_b (ID int not null,`TEXT` TEXT,key (ID));
Query OK, 0 rows affected (0.03 sec)
mysql> INSERT INTO table_a (NAME) VALUES ('DAN'),('RON'),('JANE');
Query OK, 3 rows affected (0.02 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> INSERT INTO table_b (ID,`TEXT`) VALUES (2,'APPLE'),(2,'BANANA'),(2,'COFFEE');
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> SELECT A.*,IFNULL(GROUP_CONCAT(B.`TEXT`),'') `TEXT`
-> FROM table_a A LEFT JOIN table_b B USING (ID) GROUP BY A.ID;
+----+------+---------------------+
| ID | NAME | TEXT |
+----+------+---------------------+
| 1 | DAN | |
| 2 | RON | APPLE,BANANA,COFFEE |
| 3 | JANE | |
+----+------+---------------------+
3 rows in set (0.00 sec)
mysql>
you only need to use GROUP_CONCAT
SELECT a.ID, a.Name, GROUP_CONCAT(b.text) textList
FROM table_a a
INNER JOIN table_b b
ON a.ID = b.ID
-- WHERE ...if you want extra condition.
GROUP BY a.ID, a.Name
SQLFiddle Demo
GROUP_CONCAT
You can use the GROUP_CONCAT function in MySQL to combine results from a related table:
select
a.id,
a.name,
group_concat(b.text) text
from
table_a a
join
table_b b on a.id = b.id
group by a.id
Sample Output:
| ID | NAME | TEXT |
------------------------------------
| 2 | RON | APPLE,BANANA,COFFEE |
Demo: http://www.sqlfiddle.com/#!2/e3584/9

MySQL aggregate function problem

In the following example, why does the min() query return results, but the max() query does not?
mysql> create table t(id int, a int);
Query OK, 0 rows affected (0.10 sec)
mysql> insert into t(id, a) values(1, 1);
Query OK, 1 row affected (0.03 sec)
mysql> insert into t(id, a) values(1, 2);
Query OK, 1 row affected (0.02 sec)
mysql> select * from t
-> ;
+------+------+
| id | a |
+------+------+
| 1 | 1 |
| 1 | 2 |
+------+------+
2 rows in set (0.00 sec)
mysql> select * from t where a < 4;
+------+------+
| id | a |
+------+------+
| 1 | 1 |
| 1 | 2 |
+------+------+
2 rows in set (0.00 sec)
mysql> select * from t where a < 4 having a = max(a);
Empty set (0.00 sec)
mysql> select * from t where a < 4 having a = min(a);
+------+------+
| id | a |
+------+------+
| 1 | 1 |
+------+------+
1 row in set (0.00 sec)
The HAVING clause is used to filter groups of rows. You reference min(a) and max(a) which (in the absence of any GROUP BY clause) aggregate over all a values in the table but then use a comparison against a single a value.
So which a value is MySQL supposed to use? All other RDBMSs that I know of would throw an error at this point however MySQL does allow this. From the docs
Standard SQL does not permit the HAVING clause to name any column
not found in the GROUP BY clause unless it is enclosed in an aggregate
function. MySQL permits the use of such columns to simplify
calculations. This extension assumes that the nongrouped columns will
have the same group-wise values. Otherwise, the result is
indeterminate.
So in your case from the results you are getting it appears that it ended up using 1 as the scalar value for a but this behaviour is not guaranteed and it could equally well have used 2 or any other existing a value.

How to select from MySQL where a SET does not equal a value?

we have an issue because this is how the table was setup. How do we select from a table where a set does not contain a value? If we have a set with one,two and we do
SELECT *
FROM table
WHERE column NOT IN('one')
we will still get that row. What is the correct syntax for this?
Thanks
this is what worked:
SELECT *, FIND_IN_SET('hidden', props) As hidden
FROM gt_content
HAVING hidden IS NULL
Try:
SELECT *
FROM table
WHERE FIND_IN_SET('one',column) = 0
Some test I did:
mysql> CREATE TABLE setTest (s SET('a','b','c','d'));
Query OK, 0 rows affected (0.60 sec)
mysql> INSERT INTO setTest VALUES ('a'),('a,b'),('b'),('a,c'),('c,d');
Query OK, 5 rows affected (0.14 sec)
Records: 5 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM setTest;
+------+
| s |
+------+
| a |
| a,b |
| b |
| a,c |
| c,d |
+------+
5 rows in set (0.20 sec)
mysql> SELECT * FROM setTest WHERE FIND_IN_SET('a',s) = 0;
+------+
| s |
+------+
| b |
| c,d |
+------+
2 rows in set (0.12 sec)
mysql> SELECT * FROM setTest WHERE FIND_IN_SET('b',s) = 0;
+------+
| s |
+------+
| a |
| a,c |
| c,d |
+------+
3 rows in set (0.00 sec)
mysql> SELECT * FROM setTest WHERE FIND_IN_SET('b',s) > 0;
+------+
| s |
+------+
| a,b |
| b |
+------+
2 rows in set (0.04 sec)
From the mysql manual at http://dev.mysql.com/doc/refman/5.0/en/set.html:
Normally, you search for SET values using the FIND_IN_SET() function or the LIKE operator:
SELECT * FROM tbl_name WHERE FIND_IN_SET('value',set_col)>0;
SELECT * FROM tbl_name WHERE set_col LIKE '%value%';
The first statement finds rows where set_col contains the value set member. The second is similar, but not the same: It finds rows where set_col contains value anywhere, even as a substring of another set member.

SQL query: Delete a entry which is not present in a join table?

I’m going to delete all users which has no subscription but I seem to run into problems each time I try to detect the users.
My schemas look like this:
Users = {userid, name}
Subscriptionoffering = {userid, subscriptionname}
Now, what I’m going to do is to delete all users in the user table there has a count of zero in the subscriptionoffering table. Or said in other words: All users which userid is not present in the subscriptionoffering table. I’ve tried with different queries but with no result.
I’ve tried to say where user.userid <> subscriptionoffering.userid, but that doesn’t seem to work. Do anyone know how to create the correct query?
Thanks
Mestika
delete from Users
where UserID not in
(select userid from subscriptionOffering)
You can use a multi-table delete statement with a left outer join and focus on the non-matching rows like this:
delete u from Users as u
left outer join Subscriptionoffering as so
on so.userid = u.userid
where so.userid is null;
Here is some test code to prove it:
mysql> create table Users (userid int unsigned primary key auto_increment) engine = innodb;
Query OK, 0 rows affected (0.43 sec)
mysql> create table Subscriptionoffering (userid int unsigned not null, subscriptionname varchar(32) not null, foreign key (userid) references Users(userid)) engine = innodb;
Query OK, 0 rows affected (0.41 sec)
mysql> insert into Users () values (), (), (), (), ();
Query OK, 5 rows affected (0.38 sec)
Records: 5 Duplicates: 0 Warnings: 0
mysql> select * from Users;
+--------+
| userid |
+--------+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
+--------+
5 rows in set (0.00 sec)
mysql> insert into Subscriptionoffering (userid, subscriptionname) values (1, 'One'), (3, 'Three'), (5, 'Five');
Query OK, 3 rows affected (0.31 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> select * from Subscriptionoffering;
+--------+------------------+
| userid | subscriptionname |
+--------+------------------+
| 1 | One |
| 3 | Three |
| 5 | Five |
+--------+------------------+
3 rows in set (0.00 sec)
mysql> delete u from Users as u
-> left outer join Subscriptionoffering as so
-> on so.userid = u.userid
-> where so.userid is null;
Query OK, 2 rows affected (0.36 sec)
mysql> select * from Users;
+--------+
| userid |
+--------+
| 1 |
| 3 |
| 5 |
+--------+
3 rows in set (0.00 sec)