MySQL searching from comma separated string - mysql

I have Structure like this table.
ID Category Publisher
1 1,2 A
2 1 B
3 2 C
4 1 D
5 2 E
6 2,3,1 F
I want a query, when i search for category for 1,3 then it's return
following
I tried but don't get any optimized way.
ID Category Publisher
1 1,2 A
2 1 B
4 1 D
6 2,3,1 F

select * from your_table
where find_in_set(1, category) > 0
or find_in_set(3, category) > 0
But actually you should never store multiple values in a single column. Better change your table design.

While pure SQL does not offer the tools to compare between two sets, this can be implemented in code (JavaScript/PHP) or using stored procedures.
In order to use pure SQL, you could implement a stored procedure to return the comma-separated string as a single-column temporary table (this answer and this post can give you an idea for implementing this part).
And then, utilizing what you have created, assuming the function is implemented
STR_SPLIT(<string>, <delimiter>) and returns a table with a single column named colName, you could write:
SELECT DISTINCT `tblName`.*
FROM `tblName`
INNER JOIN STR_SPLIT('1,3',',') `given`
ON FIND_IN_SET(`given`.`colName`, `category`) > 0
This will take each value and match it separately, which will created duplicates that are going to be eliminated by the DISTINCT statement, making this a non-ideal solution.
I'd recommend using a reference table in this case of data, which will have made this issue a breeze to handle, or implementing a partial solution and finishing code-side.

Related

Querying for multiple rows in a table (and its pair in the same table) where one half of the pair is connected to one id in another table

This is a random question that I am trying to figure out in SQL.
Say you have a table whereby the rows come in pairs. So you will have:
same_table
ID Name Family_Id Other_id
1 B. 1. 2 --> This ID is id 2 in the same table.
2. C. nil nil
3 D. 1 4 --> this ID is also the next row in the table.
4 E. nil nil
Sorry, this is incredibly convoluted and hard to explain. Essentially I need to get the rows connected to family_id 1 AND the other part of the pair.
So I know SELECT * FROM same_table WHERE family_id=1 --> will get 1 half.
HOW do I write a query where I am looking specifically for the rows connected to a specific family_id and that rows pair.
Sorry... poorly explained but I don't know how else to ask it.
Well, if the hierarchy is only one level deep (as in your example data and explanation), you can use exists:
select t.*
from same_table t
where t.family_id = :input or
exists (select 1
from same_table t2
where t2.other_id = t.id and t2.famil_id = :input
);

Trying to determine differences in one column

I have 3 columns and I'm trying to determine the differences in one of the columns. Here is an example:
drug_id ndc item_id
1 12345678910 1234
1 12345678910 1235
There are multiple drug_id's and each drug_id has multiple ndcs. (A particular ndc could appear in multiple drug_ids). Essentially, I want to find where there is a difference in item_id based on the drug_id and ndc.
Any tips?
DISTINCT should work.
SELECT DISTINCT D.Drug_ID, D.ndc, D.item_id
FROM Table d;
If you're unfamiliar on SQL Predicates, you can learn more about them here for Access specifically.

MYSQL query with comma seperated field value into array

is there any way, i can get a field values (comma seperate) into an array or temporary table.
ex: i have field following with values 3,7,23,45
i want get them into an array without using PHP, or into a temporary table.
as i need to do some joint queries based on those values.
any help is appreciated
thanks
my table name is: shoes
field name is following
sample table values are like these
+----------+-----------+
userId following
+----------+-----------+
1 5,7,8,12
2 5,2,1,67
now, when i search for userId 1, i want to get values 5,7,8,12 into an array or temp table.
It is possible although not particularly quick. The best solution is to redesign the database to move the comma separated list into a different table, with one row for each comma separated element.
However if you want an SQL way to do it then something like the following will do it (this relies on having a table called integers with a single column called i, with 10 rows with the values 0 to 9).
SELECT DISTINCT shoes.userId , substring_index(substring_index(shoes.FollowingIdString, ',', anInt), ',', -1) AS SplitField
FROM shoes,
(SELECT a.i+b.i*10+c.i*100 AS anInt
FROM integers a, integers b, integers c) Sub1
HAVING SplitField IS NOT NULL
Assuming you have a table PersonList which has multiple columns and this is the table where you want to join to get the name of the followers list. eg
PersonTable
ID Name
1 AAA
2 BBB
there is a mysql function called FIND_IN_SET, eg
SELECT a.userID, GROUP_CONCAT(b.Name)
FROM Follower a
INNER JOIN Person b
ON FIND_IN_SET(b.id, a.following) > 0
GROUP BY a.userID
SQLFiddle Demo

How to convert list field into many-to-many table in MySQL

I have inherited a database in which a person table has a field called authorised_areas. The front end allows the user to choose multiple entries from a pick list (populated with values from the description field of the area table) and then sets the value of authorised_areas to a comma-delimited list. I am migrating this to a MySQL database and while I'm at it, I would like to improve the database integrity by removing the authorised_areas field from the person table and create a many-to-many table person_area which would just hold pairs of person-area keys. There are several hundred person records, so I would like to find a way to do this efficiently using a few MySQL statements, rather than individual insert or update statements.
Just to clarify, the current structure is something like:
person
id name authorised_areas
1 Joe room12, room153, 2nd floor office
2 Anna room12, room17
area
id description
1 room12
2 room17
3 room153
4 2nd floor office
...but what I would like is:
person
id name
1 Joe
2 Anna
area
id description
1 room12
2 room17
3 room153
4 2nd floor office
person_area
person_id area_id
1 1
1 3
1 4
2 1
2 2
There is no reference to the area id in the person table (and some text values in the lists are not exactly the same as the description in the area table), so this would need to be done by text or pattern matching. Would I be better off just writing some php code to split the strings, find the matches and insert the appropriate values into the many-to-many table?
I'd be surprised if I were the first person to have to do this, but google search didn't turn up anything useful (perhaps I didn't use the appropriate search terms?) If anyone could offer some suggestions of a way to do this efficiently, I would very much appreciate it.
While it is possible to do this I would suggest that as a one off job it would probably be quicker to knock up a php (or your favorite scripting language) script to do it with multiple inserts.
If you must do it in a single statement then have a table of integers (0 to 9, cross join against itself to get as big a range as you need) and join this against your original table, using string functions to get the Xth comma and from that each of the values for each row.
Possible, and I have done it but mainly to show that having a delimited field is not a good idea. It would likely be FAR quicker to knock up a script with multiple inserts.
You could base an insert on something like this SELECT (although this also comes up with a blank line for each person as well as the relevant ones, and will only cope with up to 1000 authorised areas per person)
SELECT z.id, z.name, x.an_authorised_area
FROM person z
LEFT OUTER JOIN (
SELECT DISTINCT a.id, SUBSTRING_INDEX( SUBSTRING_INDEX( authorised_areas, ",", b.ournumbers ) , ",", -1 ) AS an_authorised_area
FROM person a, (
SELECT hundreds.i *100 + tens.i *10 + units.i AS ournumbers
FROM integers AS hundreds
CROSS JOIN integers AS tens
CROSS JOIN integers AS units
)b
)x ON z.id = x.id

SQL Statement to create a table as a result of a count operation?

Let's say you got a table like this
id terms
1 a
2 c
3 a
4 b
5 b
6 a
7 a
8 b
9 b
10 b
and you want to end up with a report like this;
terms count
a 4
b 5
c 1
So you run this over the first table
SELECT terms, COUNT( id) AS count
FROM table
GROUP BY terms
ORDER BY terms DESC
So far so good.
But the above SQL statment puts the report view on the browser. Well, I want to save that data into a SQL.
So, what SQL command do I need to insert the results of that report into a table?
Assume that you already created a table called reports with this;
create table reports (terms varchar(500), count (int))
Let's assume that the reports table is empty and we just want to populate it with the following view - with a one-liner. The question I'm asking is how?
terms count
a 4
b 5
c 1
As simple as that:
INSERT INTO reports
SELECT terms, COUNT( id) AS count
FROM table
GROUP BY terms
ORDER BY terms DESC
if the table exists already:
Insert reports
SELECT terms, COUNT(*) AS count
FROM table
GROUP BY terms
if not:
SELECT terms, COUNT(*) AS count
into reports
FROM table
GROUP BY terms