Mysql commaseparated column matching from another table - php

I would like to select all matches from a commaseparated column in table2, where column could be like this: 0,1,2 OR 2,4,5 OR 2,5 OR 1,3,5 etc.
I have tried with:
SELECT * from table where 1,3,5 IN(SELECT commaseparated FROM table2) WHERE ..
But error on statement when using commas.
I've also tried using REGEXP but in my case i need to search for all matches within 1,3,5
How can i solve this one? :)

Can't do that in standard SQL. it's
WHERE singlevalue IN (list, of, values)
if you want to compare lists against lists, you should revamp your tables so they're properly normalized. Storing formatted data in a field basically negates the purpose of having a relational database - you can't establish relationships with the data if it's not in a format that allows relationships to be formed.
If those CSV lists were in sub-tables, you could do a very simple JOIN query to meet your specifications.

Related

groupby with column field having like column

I am using group by for like statement as i have database structure like this.
I want to get the count of workingzone groupby.but if i try to group by, then wrong output will appear as output will group by 99 and 99, as in figure.
My sql code is:
select count(organization),working_zone from `projects` where `district` = 12 and (`working_zone` = 99 or `working_zone` LIKE "99," or `working_zone` LIKE ",99") group by `organization`;
my desired result is:
count |working_zone
____6| 99
____3| 100
(99),(,99),(99,) should be grouped by doing sum and result should be 6.
You have an awful data structure -- although I wouldn't be surprised if the data is okay and you are really working off the result of a (reasonable) query. You should not be storing raw data in comma-delimited lists. Instead, use junction tables.
Why is having a separate row for each pair the SQLish way of storing data? Consider these reasons:
SQL has pretty based string functions (compared to other programming environments).
Data should be stored in its native type; don't store numbers as strings.
Foreign key relationships should be explicitly declared, and you can't declare a foreign key relationship using comma-delimited strings.
The primary SQL mechanism for optimizing queries are indexes, and comma-delimited lists preclude the use of indexes.
Sometimes, though, you are stuck with someone else's bad design decisions. If so, one solution uses a table of working zones:
select count(*), wz.working_zone
from projects p join
working_zones wz
on find_in_set(wz.working_zone, p.working_zone) > 0
where p.district; = 12 and
find_in_set(99, p.working_zone) > 0
group by wz.working_zone;
SELECT COUNT(organization),working_zone FROM table WHERE working_zone HAVING '99'
UNION ALL
SELECT COUNT(organization),SUBSTRING(working_zone,4) FROM table WHERE working_zone = '99,100'

Get an array of all columns starting with the same characters.

This is quite difficult to explain in the title, so I'll do my best here. Basically I have a column in a MySQL products table that contains rows like:
FEL10
FEL20
FEL30
PRO05
PRO07
PRO08
VAI12
VAI13
VAI14
These are the categories ("FEL","PRO","VAI") and a identification number of my products ("10", "20" and so on). I need an SQL select query that creates me a textual array like:
FEL*
PRO*
VAI*
With this array I need to create a listbox, that allows me to choose a category (regardless of the identification number). Once I choose a category, let's say PRO*, I will need to do the reverse action: print all the products info related to PRO05, PRO07 and PRO08.
How do you think you can achieve this? I have been trying using the DISTINCT statement but I need to filter only the first characters, otherwise it will be useless. I also tried the SUBSTRING() and LEFT() functions, but they seem not to be working (I get an SQL Syntax error).
--
Thanks for your help as always
What is wrong with?
SELECT distinct left(col, 3) as category FROM `table1`
MySQL LIKE to the resque:
SELECT col1 FROM table1 WHERE col1 LIKE 'FEL%';
This way you have to add all cases using OR.
Alternative - REGEXP:
SELECT col1 FROM table1 WHERE col1 REGEXP '(FEL|PRO|VAI).*'
Then it's just a matter of writing proper regex.
I would use extra col to group your items - to avoid such selecting altogether (which should be quite expensive on bigger dataset).
https://dev.mysql.com/doc/refman/5.1/en/regexp.html#operator_regexp
To get the list of the 3-letter codes use:
select distinct left(combicode, 3)
from mytable;
When a user selects one of the values use this to get all matching entries:
select *
from mytable
where combicode like concat(#category, '%');
(Aside from that: It's a bad idea to have concatenated values in one column. Why not have one column for the category and another for the product code? Then there would be no problem at all.)

Mysql with regular expression

I have a query regarding regular expression.I have design a table which contain three column one column contain member ids which are separated by commas.I am showing you my table structure.Please follow
send_id member_id
1 1211,23,34
2 1,23
I want to select only send_id 2 data which contain member_id as 1.
this is the query that i am using
SELECT * FROM table WHERE column REGEXP '^[1]+$';
but this query giving me both row.Please help me.
With Regards
Rahul
Never store separate values in one column
Normalize your structure like
send_id member_id
1 1211
1 23
1 34
2 1
2 23
If you still want your regex, then it will be
SELECT * FROM t WHERE column REGEXP '(^|[^0-9])1([^0-9]|$)'
First, you should be normalizing your data so you're not in this horrible mess in the first place. Here's a good resource explaining normalization.
Second, I believe your problem lies with your regular expression. Try this instead:
SELECT * FROM table WHERE column REGEXP '^[1]$';
The regular expression you're using uses the [1]+ group. The + means it has to match [1] 1 or more times, hence why you're getting two rows instead of one. Removing the + means it will match [1] once.
However, that still won't fix your problem, as more than one row contains 1. This is why normalization is so important.
Having multiple values inside a column isn't a good practice for designing a DB.
You should normalize your data, i.e., put just one piece of atomic information inside each element of your table.
You can find more information regarding to this in Wikipedia:
http://en.wikipedia.org/wiki/Database_normalization
Like they have told you, perfect solution would be normalize your data, I think Alma Do Mundo answer explains it quite well.
If you want to use REGEXP anyway you have to take in account four approaches; id is the only one, id is the first, id is in the middle and id is at the end. I have use id=74 for the example:
SELECT * FROM table WHERE member_id REGEXP '(^74$|^74,|,74,|,74$)';
depending on your requirements, you should either normalize your data i.e. make 3 tables, one with the send ID, one with the member id, and one that combines the two, then you can link them up with INNER JOINS.
However, if you are going to do it that way, you can use a "WHERE member_id LIKE %1%" to pull in all the relevant fields. You'll have to use the application to filter the relevant records.
In any case, if you're not going to normalize the data you will have to use the front end to filter out the results.
An example of the inner join syntax would look like this
SELECT * FROM SendTable
JOIN Send_Member ON SendTable.send_id = Send_Member.send_id
JOIN Member ON Member.member_id = Send_Member.member_id
WHERE Member.member_id = 1;
where the schema looks like:
Sendtable:
send_Id (primary key)
...other fields
Send_Member:
send_id (primary key and foreign key to SendTable)
member_id (primary key and foreign key to member)
...any fields you might want that are relevant to the particular send table and member table link
Member:
member_id (primarykey)
...other fields

splitting data in a table column for search

I was working with a simple mysql table in php when I came across this problem and I am wondering if there is a solution to this.
The table holds a username and his locations in a comma separated format.
id|user|locations
------------------
1 |abc | A, B, C
------------------
2 |xyz | P, Q, R
I was wondering if there was any way to write a mysql query so that it would return me a user who has location as A.
Basically if one of the values among the comma separated values match, the record should be returned.
I know it is a better way to store them as separate records, but I was just curious if such a retrieval is possible.
Thanks in advance.
Ideally, you should consider normalizing the data so you are not storing the comma separated list.
But if you cannot alter the table structure, MySQL has a FIND_IN_SET() function that can be used to return the rows that match the value you want:
select id, user, locations
from yourtable
where find_in_set('A', locations)
See SQL Fiddle with Demo
We think
the following query may help you -
SELECT * FROM table WHERE column REGEXP '(^|,)A($|,)'
You can have a useful link in -
How to query comma delimited field of table to see if number is within the field

DB Design; or Conditional Selects with json data

I have a DB with several tables that contain basic, static ID-to-name data. 2 Columns only in each of these reference tables.
I then have another table that will be receiving data input by users. Each instance of user input will have it's own row with a timestamp, but the important columns here will contain either one, or several of the ID's related to names in one of the other tables. For the ease of submitting and retrieving this information I opted to input it as text, in json format.
Everything was going great until I realized I'm going to need to Join the big table with the little tables to reference the names to the ID's. I need to return the IDs in the results as well.
An example of what a few rows in this table might look like:
Column 1 | Column 2 | Timestamp
["715835199","91158582","90516801"] | ["11987","11987","22474"] | 2012-08-28 21:18:48
["715835199"] | ["0"] | 2012-08-28 21:22:48
["91158582","90516801"] | ["11987"] | 2012-08-28 21:25:48
There WILL be repeats of the ID#'s input in this table, but not necessarily in the same groupings, hence why I put the ID to name pairings in a separate table.
Is it possible to do a WHERE name='any-of-these-json-values'? Am I best off doing a ghetto join in php after I query the main table to pull the IDs for the names I need to include? Or do I just need to redo the design of the data input table entirely?
First of all:
Never, ever put more than one information into one field, if you want to access them seperately. Never.
That said, I think you will need to create a full N:M relation, which includes a join table: One row in your example table will need to be replaced by 1-N rows in the join table.
A tricky join with string matching will perform acceptably only for a very small number of rows, and the WHERE name='any-of-these-json-values' is impossible in your construct: MySQL doesn't "understand", that this is a JSON array - it sees it as unstructured text. On a join table, this clause comes quite naturally as WHERE somecolumn IN (1234,5678,8012)
Edit
Assuming your Column 1 contains arrays of IDs in table1 and Column 2 carries arrays of IDs in table2 you would have to do something like
CREATE TABLE t1t2join (
t1id INT NOT NULL ,
t2id INT NOT NULL ,
`Timestamp` DATETIME NOT NULL ,
PRIMARY KEY (t1id,t2id,`Timestamp`) ,
KEY (t2id)
)
(you might want to sanity-check the keys)
And on an insert do the following (in pseudo-code)
Remember timestamp
Cycle all permutations of (Column1,Column2) given by user
Create row
So for your third example row, the SQL would be:
SELECT #now:=NOW();
INSERT INTO t1t2join VALUES
(91158582,11987,#now),
(90516801,11987,#now);

Categories