search comma separated values in mysql using php - php

I am having a bit of a problem running a select query on a database. Some of the data is held as a list of comma separated values, an example:
Table: example_tbl
| Id | standardid | subjectid |
| 1 | 1,2,3 | 8,10,3 |
| 2 | 7,6,12 | 18,19,2 |
| 3 | 10,11,12 | 4,3,7 |
And an example of the kind of thing I am trying to run:
select * from table where standardid in (7,10) and subjectid in (2,3,4)
select * from table where FIND_IN_SET(7,10,standardid) and FIND_IN_SET(2,3,4,subjectid)
Thanks in advance for anything you can tell me.

comma separated values in a database are inherently problematic and inefficient, and it is far, far better to normalise your database design; but if you check the syntax for FIND_IN_SET() it looks for a single value in the set, not matches several values in the set.
To use it for multiple values, you need to use the function several times:
select * from table
where (FIND_IN_SET(7,standardid)
OR FIND_IN_SET(10,standardid))
and (FIND_IN_SET(2,subjectid)
OR FIND_IN_SET(3,subjectid)
OR FIND_IN_SET(4,subjectid))

Related

SQL QUERY how to select column by other constraints

I am using backpack-crud controller for
PHP-Laravel.
With the crudController given by backpack (library), all I have to do
is to query it with Laravel Eloquent (also raw sql is possible) queries.
Than the Backpack library will automatically
print the listview for me.
But I am struggling with this difficult query.
The thing is that I have 4 columns,
session_id | column_id | batch | data
10 | 1 | 1 | data1
10 | 2 | 1 | data2
10 | 1 | 2 | data1*
10 | 2 | 2 | data2*
Let's say this is the data I have.
I want to display this grouping by session_id, batch,
and ordering within row by column_id.
so the result query would be something like
1 : data1 data2
2 : data1* data2*
If there is a third batch with data
session_id | column_id | batch | data
10 | 1 | 3 | data1**
Then it would appear under the third batch as
3 : data1**
I can do this with code but not with sql.
Any advice would be grateful.
This looks like a PIVOT in sql server. Unfortunately mysql does not have this feature.
I can give you an approximate raw mysql query using GROUP_CONCAT. Assuming your table name is mytable.
SELECT
session_id,
batch,
GROUP_CONCAT(data ORDER BY column_id SEPARATOR ', ') AS dataList
FROM mytable
GROUP BY session_id, batch
Then you can split the aliased dataList column using given separator (here I've used ,).
You may change the separator according to the data contain in data column as you wish.
Hope this helps to you.

Splitting the result in while loop

Here i use a query for getting last two collision occurring dates of a licence number as follows:
<?php
$licence=$_POST['licence'];
$sel=mysqli_query($con,"select cdate from tblcollision where licence_number='$licence'");
while($s=mysqli_fetch_row($sel))
{
echo $s[2];
}
?>
I wish to split the result in to separate fields. That means date1 in a text field and date2 in another text field. Actually i didn't get any idea. Please help me.
My db design is
+--------------------------------------------------+
| CID | ID | LICENCE_NUMBER | CDATE |
+--------------------------------------------------+
| 1 | 1 | 3/4858/2012 | 2018-02-06 |
| 2 | 1 | 3/4858/2012 | 2018-03-20 |
+--------------------------------------------------+
As stated by mickmackusa, if the query is filtered for a single licence number, there is no point to group result in the SQL statement and then explode the result in PHP. Just read the rows and make the calculation on the resulting dates.
However, in a more general way, if dealing with several licences, grouping can be done within the SQL statement. Despite the added cost of exploding the result, it will simplify the grouping process.
You need to use GROUP_CONCAT in your query:
SELECT licence_number, GROUP_CONCAT(cdate) AS Events_dates
FROM tblcollision
WHERE licence_number='$licence'
GROUP BY licence_number;
This will return:
3/4858/2012 | 2018-02-06, 2018-03-20

how to use codeigniter where in on comma seperated row values

I am using codeigniter for my project and implementing search. I want to filter users from users table with cars they own. Structure of this table is shown below
+-----+----------+---------------------+---------------+
| #id | username | cars | other_details |
+-----+----------+---------------------+---------------+
| 1 | MAC | Jaguar,Porche | -- |
| 2 | DEV | Porche,Ferrari,Ford | -- |
| 3 | MONICA | Ford,Audi | -- |
+-----+----------+---------------------+---------------+
On front end, I am selecting cars from checkboxes which are returning car array for find users who have these cars like ["Porche","Ferrari"]. I am not able to find solution for how to get users using codeigniter active records in model. Please help me find out how to get users/rows having cars available in array.
Thanks in advance.
Finally, I find answer.First I had implode array with comma(,) and then use sql query and regular expression for getting an answer like this;
$this->db->sql("select * from users where `cars` NOT REGEXP '$cars'");
This query give data according to my requirement.

append more than one value in single row using php

I have a table called user having 3 columns namely id, name and phone no.
i want insert data like below clip.
+----+---------------+---------------------+-
| id | name | phone no |
+----+---------------+---------------------+-
| 1 | mahadev | +91 XXXXX |
| 2 | swamy | +91 YYYYY |
| | | +91 ZZZZZ |
| 3 | charlie | +91 AAAAA |
| | | |
+----+---------------+---------------------+-
Here question is how can i add more than one values (one by one) to same row as showing id = 2 in above clip.
Could anyone please help me on this?
Thanks in advance.
You cannot do what you intended, how you intended. And for a reason.
One possible solution (bad), would be to make id non-unique and then insert two times id 2, name swamy, phone for two different phones.
Proper solution is to have two tables. One is your current user, which would have only id and name.
Second table is phone_numbers which would have user_id and phone_no. Primary key on that table would be composite of user_id and phone_no so it would prevent duplicates. Then in that table you can insert as many numbers as you need.
In your example you would have two rows with user_id=2, one for each phone number.
Then it is only a matter JOIN to join the two tables together and display your results.
SQL architecture don't allow such things. You need to use more than one row or you can use more than one table with foreign keys. Or you can serialize(phone no) before you put it into mysql.
One possible solution could be creating an array of that data and then storing it with serialize() function.
Small example:
$phones_array = array('phone_a' => '+91 YYYYY', 'phone_b' => '+91 ZZZZZ');
serialize($phones_array);
Now your data are serialized into a string, trying var_dump($phones_array) you should get:
string 'a:2:{s:7:"phone_a";s:9:"+91 YYYYY";s:7:"phone_b";s:9:"+91 ZZZZZ";}' (length=66)
You can now insert this value into your table
You can retrieve this data with:
unserialize($phones_array);

WHERE vs HAVING in generated queries

I know that this title is overused, but it seems that my kind of question is not answered yet.
So, the problem is like this:
I have a table structure made of four tables (tables, rows, cols, values) that I use to recreate the behavior of the information_schema (in a way).
In php I am generating queries to retrieve the data, and the result would still look like a normal table:
SELECT
(SELECT value FROM `values` WHERE `col` = "3" and row = rows.id) as "col1",
(SELECT value FROM `values` WHERE `col` = "4" and row = rows.id) as "col2"
FROM rows WHERE `table` = (SELECT id FROM tables WHERE name = 'table1')
HAVING (col2 LIKE "%4%")
OR
SELECT * FROM
(SELECT
(SELECT value FROM `values` WHERE `col` = "3" and row = rows.id) as "col1",
(SELECT value FROM `values` WHERE `col` = "4" and row = rows.id) as "col2"
FROM rows WHERE `table` = (SELECT id FROM tables WHERE name = 'table1')) d
WHERE col2 LIKE "%4%"
note that the part where I define the columns of the result is generated by a php script. It is less important why I am doing this, but I want to extend this algorithm that generates the queries for a broader use.
And we got to the core problem, I have to decide if I will generate a where or a having part for the query, and I know when to use them both, the problem is my algorithm doesn't and I have to make a few extra checks for this. But the two above queries are equivalent, I can always put any query in a sub-query, give it an alias, and use where on the new derived table. But I wonder if I will have problems with the performance or not, or if this will turn back on me in an unexpected way.
I know how they both work, and how where is supposed to be faster, but this is why I came here to ask. Hopefully I made myself understood, please excuse my english and the long useless turns of phrases, and all.
EDIT 1
I already know the difference between the two, and all that implies, my only dilemma is that using custom columns from other tables, with variable numbers and size, and trying to achieve the same result as using a normally created table implies that I must use HAVING for filtering the derived tables columns, at the same time having the option to wrap it up in a subquery and use where normally, this probably will create a temporary table that will be filtered afterwards. Will this affect performance for a large database? And unfortunately I cannot test this right now, as I do not afford to fill the database with over 1 billion entries (that will be something like this: 1 billion in rows table, 5 billions in values table, as every row have 5 columns, 5 rows in cols table and 1 row in tables table = 6,000,006 entries in total)
right now my database looks like this:
+----+--------+-----------+------+
| id | name | title | dets |
+----+--------+-----------+------+
| 1 | table1 | Table One | |
+----+--------+-----------+------+
+----+-------+------+
| id | table | name |
+----+-------+------+
| 3 | 1 | col1 |
| 4 | 1 | col2 |
+----+-------+------+
where `table` is a foreign key from table `tables`
+----+-------+-------+
| id | table | extra |
+----+-------+-------+
| 1 | 1 | |
| 2 | 1 | |
+----+-------+-------+
where `table` is a foreign key from table `tables`
+----+-----+-----+----------+
| id | row | col | value |
+----+-----+-----+----------+
| 1 | 1 | 3 | 13 |
| 2 | 1 | 4 | 14 |
| 6 | 2 | 4 | 24 |
| 9 | 2 | 3 | asdfghjk |
+----+-----+-----+----------+
where `row` is a foreign key from table `rows`
where `col` is a foreign key from table `cols`
EDIT 2
The conditions are there just for demonstration purposes!
EDIT 3
For only two rows, it seems there is a difference between the two, the one using having is 0,0008 and the one using where is 0.0014-0.0019. I wonder if this will affect performance for large numbers of rows and columns
EDIT 4
The result of the two queries is identical, and that is:
+----------+------+
| col1 | col2 |
+----------+------+
| 13 | 14 |
| asdfghjk | 24 |
+----------+------+
HAVING is specifically for GROUP BY, WHERE is to provide conditional parameters. See also WHERE vs HAVING
I believe the having clause would be faster in this case, as you're defining specific values, as opposed to reading through the values and looking for a match.
See: http://database-programmer.blogspot.com/2008/04/group-by-having-sum-avg-and-count.html
Basically, WHERE filters out columns before passing them to an aggregate function, but HAVING filters the aggregate function's results.
you could do it like that
WHERE col2 In (14,24)
your code WHERE col2 LIKE "%4%" is bad idea so what about col2 = 34 it will be also selected.

Categories