How to group data from database by particular column? - php

I have the following dataset:
ToDo_Name List_ID
-------------------------------
Read book 1
Study English 2
Do excercises 2
Sleep 1
Eat 1
I need to group this data by List_ID creating the array like this (and send it as json to frontend):
$result = array(
array("listId" => 1, array('Read book', 'Sleep', 'Eat ')),
array("listId" => 2, array('Study English', 'Do excercises'))
);
I can't understand - should I do this using some SQL query or PHP array methods? Will be happy to hear any advices...

You could use group concat ..
select list_id, group_concat(ToDo_Name)
from mytable
group by list_id

Related

PHP/SQL Find duplicate rows in a column, with the condition that another column is different

I need an SQL query to do the following task:
I have two columns. Column 'foo' and column 'bar'.
The query needs to return results if and only if column 'foo' has different values but 'bar' has the same values.
For example:
Foo Bar
---------------------
1 John
1 Lee
2 James
3 Robin <- the value '3' needs to be returned
3 Sally
1 Peter
1 John
4 Brian
2 Robin <- the value '2' needs to be returned
If I was to run the query on the above dataset, then both rows indicated withe arrows above would be returned, because 'bar' is the same on both rows, but 'foo' is different.
Any help would be appreciated.
Thank you.
You can do what you want using exists:
select t.*
from t
where exists (select 1
from t t2
where t2.bar = t.bar and t2.foo <> t.foo
);

group by and group_concat alternative

Using GROUP_CONCAT() usually invokes the group-by logic and creates temporary tables, which are usually a big negative for performance. Sometimes you can add the right index to avoid the temp table in a group-by query, but not in every case.
https://stackoverflow.com/a/26225148/9685125
After Reading this post, I realized that I was doing wrong, because many time I made complicated query using huge GROUP_CONCAT(). Such as
GROUP_CONCAT(DISTINCT exam.title) AS exam,
GROUP_CONCAT(subject.title, '<br/> Th - ', mark.th, ' | PR - ', mark.pr SEPARATOR ',') AS mark
But what can be alternative of GROUP_CONCAT in following situation without using subquery. I mean using only Mysql join,
For example, let see two relational database and and query to explain my problem
Student
id | Rid | name
========================
1 | 1 | john
Marks
id | std_id | th
======================
1 | 1 | 60
2 | 1 | 70
3 | 1 | 80
4 | 1 | 90
"SELECT
student.en_name, mark.th
FROM student
JOIN mark ON student.id = mark.std_id
WHERE student.id=:id;"
Column would be repeated if only use JOIN
John: 60, John: 70, John: 80, John: 90
So, I use GROUP BY. But if I assign GROUP BY to student.id, only first row is fetched
"SELECT
student.en_name, mark.th
FROM student
JOIN mark ON student.id = mark.std_id
WHERE student.id=:id
GROUP BY student.id;"
Result is
John: 60
So to get result, we have to assign that group.concat
"SELECT
student.en_name,
GROUP_CONCAT(mark.th) as mark
FROM student
JOIN mark ON student.id = mark.std_id
WHERE student.id=:id
GROUP BY student.id;"
And final and expected result using exploding array
$name=$row['en_name'];
echo "$name: <br/>";
$mrk_array = explode(',',$row['mark']);
foreach($mrk_array as $mark){
echo $mark.", ";
}
John:
60, 70, 80, 90,
Here, I don't see any alternative of GROUP_CONCAT to fetch all associated value of each Id and prevent duplicate, please help me how to replace GROUP_CONCAT from here.
Also, one friend told me
So why GROUP_CONCAT if you're "exploding" it. You might as well return a nice associative array and then deal with displaying it there.
But I can't understand, what he means ?
Too long for a comment...
With your original query, you are effectively returning an array of rows (associative arrays):
array(array('en_name' => 'John', 'mark' => 60),
array('en_name' => 'John', 'mark' => 70),
array('en_name' => 'John', 'mark' => 80),
array('en_name' => 'John', 'mark' => 90)
)
When you use GROUP BY and GROUP CONCAT, you are effectively imploding the 'mark' elements of that array to
array('en_name => 'John', 'mark' => '60,70,80,90')
and you then have to explode the array again to process the data.
If you stick with your original query, you can instead do the imploding in your application framework e.g.
$name = "";
while ($row = $result->fetch()) {
if ($row['en_name'] != $name) {
$name = $row['en_name'];
echo "$name: <br/>" . $row['mark'];
}
else {
echo ',' . $row['mark'];
}
}
Output:
John:
60,70,80,90
This will generally be a lot faster than using GROUP BY and GROUP_CONCAT in the database.

Convert Received Data from SQL and Translate

I am wanting to convert data that is queried from the database to another string. The best way I can explain what I'm trying to do is below:
I have a table called "users". Inside that table I have a column called "rank". Rank is a two-digit integer ranging from 1 to 21.
I want to convert that "1" or whichever number into more understandable text in my php file. So if your rank is set to "1", the output is "User" or what-have-you.
How do I go about doing this? I'm not sure what this process is called. I'm very new to php.
Thank you!
Create a rank table having 2 columns, id and rank:
id | rank
-------------
1 | user
2 | admin
3 | goof
Then JOIN the users table with the rank table:
SELECT u.name, r.rank
FROM users u
LEFT JOIN rank r
ON u.rank = r.id
You can store the ranks title in another table like mentioned by Jay Blanchard or you can define an array with the rank titles like this
$ranks = array(
1 => 'User',
2 => 'Administrator',
3 => 'Moderator'
);
and can echo like this
echo $ranks['rank_id_fetched_using_sql'];
rank_id_fetched_using_sql is supposed to be 1 to 21

PHP multi array (JSON) from SQL query on three tables

I hope someone can help me with this specific problem.
I'm new to PHP and MySQL but I'm trying as best as I can. Also, I know that probably similar questions have been asked, but unfortunately I tried every angle I could think of to modify those tutorials/answers to suit my needs, but unfortunately I've failed miserably..
So, here's my problem: I have 3 MySQL tables(contacts, phone numbers, and phone types) for simple phonebook, structured like this:
|ID |name | |ID |cID |tID |number| |ID |type |
-----------------------------------------------------------------------
1 John 1 1 2 123456 1 Home
2 Mary 2 2 1 234567 2 Mobile
3 Sue 3 1 3 213234 3 Work
4 2 2 444321
5 3 2 555543
The first table contains contact names, second holds the number details, and third is "static" table for referencing phone number types.
Now, I'm creating an api for simple crud app in PHP and I'm stuck at creating the array that will give me the result structured as I envisioned:
[
{"ContactID": 1,
"ContactName": "John",
"PhoneNumbers": {
"PhoneNumberID": 1,
"PhoneType": 2,
"PhoneNumber": 123456
}
},
{...},
{...}
]
The query I'm using is:
SELECT contacts.*, pt.type, pn.number, pn.id
FROM contacts
LEFT JOIN phonenumbers pn ON c.ID = pn.cID
LEFT JOIN phonetypes pt ON pn.tID = pt.ID
And now I'm stuck at PHP syntax for creating the array mentioned above. Can you help point me in the right direction please?
Also, as this is a small assignment demonstrating the CRUD functions, I'm not sure about my database, is the three table structure OK? Do I need to change it to something else?
Thanks in advance! Cheers!
If all the tables have ID columns, you need to use an alias in the SQL to distinguish phonenumbers.id from contacts.id. So change the query to:
SELECT contacts.*, pt.type, pn.number, pn.id AS phoneid
FROM contacts
LEFT JOIN phonenumbers pn ON c.ID = pn.cID
LEFT JOIN phonetypes pt ON pn.tID = pt.ID
Here's the code assuming you're using PDO; mysqli will be similar.
$result = array();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC) {
if (!isset($result[$row['ContactID']]) {
// If this is the first row for this contact, create an entry in the results
$result[$row['ContactID']] = array(
'ContactID' => $row['ID'],
'ContactName' => $row['name'],
'PhoneNumbers' => array()
);
}
// Add this phone number to the `PhoneNumbers` array
$result[$row['ContactID']]['PhoneNumbers'][] = array(
'PhoneNumberID' => $row['phoneid'],
'PhoneType' => $row['type'],
'PhoneNumber' => $row['number']
);
}
$result = array_values($result); // Convert from associative to indexed array
// Convert to JSON
echo json_encode($result);
The resulting JSON will look like this:
[
{"ContactID": 1,
"ContactName": "John",
"PhoneNumbers": [
{
"PhoneNumberID": 1,
"PhoneType": "Mobile",
"PhoneNumber": "123456"
},
{
"PhoneNumberID": 3,
"PhoneType": "Work",
"PhoneNumber": "213234"
}
},
{...},
{...}
]
PhoneNumbers is an array of all the phone numbers, and PhoneType is the type name, not its ID. If you only want the type ID, you don't need to join with phonetypes.

GROUP BY clause ignoring rows and data

As we know GROUP BY clause return data by ignoring duplicate data by specifying particular GROUP BY 'user_id' , but i want to do that GROUP BY ignore table row but i want to combine data of that row in array , means i want all data but in filtered row
i want to something like
id | name | user_id
-------------------
1 abc 20
2 trt 19
3 sdf 20
4 khg 22
5 fdf 20
6 lnm 22
id | name | user_id
-------------------
1 abc,sdf,fdf 20
2 trt 19
3 khg,lnm 22
Use GROUP_CONCAT for this. Try this query -
SELECT id, GROUP_CONCAT(name) name, user_id FROM students GROUP BY user_id
The GROUP_CONCAT function concatenates strings from a group into one string with various options.
Update
To implement it in CakePhp -
$driverlocation_data = $this->DriverLocation->find(
'all',
array(
'conditions'=>array('DriverLocation.dispensary_id'=>$dispensary_id),
'fields' => array('id', 'GROUP_CONCAT(name) name', 'user_id')
'group'=>array('DriverLocation.driver_id')
)
);
Please try this query.
Select id, GROUP_CONCAT(name), user_id FROM table_name GROUP BY user_id
I have Used group_concat for name column.

Categories