grouping datas with same group - php

I'm trying to achieve to group Data by a column named 'groups'. I've been looking this post here Categorizing mysql data into seperate html tables?
This is also applicable in my case but the same groups get separated
This is what it looked like
_____________________________________
|_____________Group ZXY_______________|
| Month | Bet | Win |Payout|
|_______________|_______|______|______|
|Name|Group|Desc| | | |
|_______________|_______|______|______|
|Name|Group|Desc| | | |
|_______________|_______|______|______|
|_____Total_____|_______|______|______|
_____________________________________
|_____________Group ZXY_______________|
| Month | Bet | Win |Payout|
|_______________|_______|______|______|
|Name|Group|Desc| | | |
|_______________|_______|______|______|
|Name|Group|Desc| | | |
|_______________|_______|______|______|
|_____Total_____|_______|______|______|
As you can see the data returned are having the same group but got separated. Must be only using 1 table in this case
Summary of my idea
Group loop
add
<table><th>..</th></table>
tags inside the variable
Data fetch loop
add
<tr><td>..</td></tr>
tags inside the variable
Here's the code
$sql='SELECT DISTINCT `groups` FROM `kiosk_data` WHERE `groups` IS NOT NULL ORDER BY `groups` ASC';
$grpData='';
$grpHr[]=array();
//this is the code I used to fill im th contents of the dropdown box
$result = $conn->query($sql);
while ($row = $result->fetch(PDO::FETCH_ASSOC))
{
if(!empty($row['groups']))
{
$selected = (isset($_GET['grp']) && $_GET['grp']==$row['groups'])?'selected="selected"':'';
$grpData.='<option value="'.$row['groups'].'"'.$selected.'>'.$row['groups'].'</option>';
$grpHr[]=$row['groups'];//took this opportunity to store the values of groups in grpHr[] Array
}
}
$sql = "SELECT COALESCE(kd.`kiosk_name`,'Total') AS 'Kiosk',
FORMAT(SUM(`casino_bets`),2) AS 'CBTotal', FORMAT(SUM(`bet_win`),2) AS 'BWTotal'
,FORMAT((`casino_bets`-`bet_win`)/`casino_bets`*100,2) AS 'Payout', groups FROM
`kiosk_data` kd LEFT JOIN `kiosk_status` ks ON kd.`kiosk_id`=ks.`kiosk_id` WHERE
`kiosk_name` IS NOT NULL AND `casino_bets` IS NOT NULL AND `bet_win` IS NOT NULL";
$result = $conn->prepare($sql);
$result ->execute();
foreach ($grpHr as $key => $value) {//iterate til the last group name
$key = $row['groups'];//I think I need to do this before entering the fetch loop
echo '<table><tr><td colspan="6">'.$row['groups'].'</td></tr><tr><th colspan="3">'.date("m",strtotime($row['date'])).'Month</th><th>Bet</th><th>Bet-Win</th><th>Payout %</th></tr>';
while ($row = $result->fetch(PDO::FETCH_ASSOC))
{
echo '<tr><td>'.$row['Kiosk'].'</td><td>'.$row['groups'].'</td><td>'.$row['city'].'</td><td>'.$row['CBTotal'].'</td><td>'.$row['BWTotal'].'</td><td>'.$row['Payout'].'</td></tr>';
}
}
Any other possible workaround for something better aside from my idea?

Assuming that your second query retrieves the needed data, please try the following version of your PHP code:
$sql='SELECT DISTINCT `groups` FROM `kiosk_data` WHERE `groups` IS NOT NULL ORDER BY `groups` ASC';
$grpData='';
$grpHr[]=array();
//this is the code I used to fill im th contents of the dropdown box
$result = $conn->query($sql);
while ($row = $result->fetch(PDO::FETCH_ASSOC))
{
if(!empty($row['groups']))
{
$selected = (isset($_GET['grp']) && $_GET['grp']==$row['groups'])?'selected="selected"':'';
$grpData.='<option value="'.$row['groups'].'"'.$selected.'>'.$row['groups'].'</option>';
$grpHr[]=$row['groups'];//took this opportunity to store the values of groups in grpHr[] Array
}
}
$sql = "SELECT COALESCE(kd.`kiosk_name`,'Total') AS 'Kiosk',
FORMAT(SUM(`casino_bets`),2) AS 'CBTotal', FORMAT(SUM(`bet_win`),2) AS 'BWTotal'
,FORMAT((`casino_bets`-`bet_win`)/`casino_bets`*100,2) AS 'Payout', groups FROM
`kiosk_data` kd LEFT JOIN `kiosk_status` ks ON kd.`kiosk_id`=ks.`kiosk_id` WHERE
`kiosk_name` IS NOT NULL AND `casino_bets` IS NOT NULL AND `bet_win` IS NOT NULL";
$result = $conn->prepare($sql);
$result ->execute();
$grpsArr = array();
while ($row = $result->fetch(PDO::FETCH_ASSOC))
{
if( ! isset($grpsArr[$row['groups']])) {
$grpsArr[$row['groups']] = array();
}
$grpsArr[$row['groups']][] = $row;
}
foreach ($grpsArr as $grpName => $grpRowArray) {
echo '<table><tr><th colspan="6">'.$grpName.'</td></tr><tr><th colspan="3">'
.date("m",strtotime($row['date']))
.' Month</th><th>Bet</th><th>Bet-Win</th><th>Payout %</th></tr>';
foreach($grpRowArray as $grpRow) {
echo '<tr><td>'.$grpRow['Kiosk'].'</td><td>'.$grpRow['groups'].'</td><td>'.$grpRow['city'].'</td><td>'.$grpRow['CBTotal'].'</td><td>'.$grpRow['BWTotal'].'</td><td>'.$grpRow['Payout'].'</td></tr>';
}
echo '</table>';
}
What has been changed are the while / foreach loops. Below please find the explanation.
while loop
$grpsArr = array();
while ($row = $result->fetch(PDO::FETCH_ASSOC))
{
if( ! isset($grpsArr[$row['groups']])) {
$grpsArr[$row['groups']] = array();
}
$grpsArr[$row['groups']][] = $row;
}
This loop iterates through all of the rows returned by your last query, putting the data into $grpsArr nested array. The section :
if( ! isset($grpsArr[$row['groups']])) {
$grpsArr[$row['groups']] = array();
}
checks whether there has already been at least one row from the $row['groups'] group throughout the iteration - if there was no such row till now, sub array is created for $row['groups'] group name;
The line:
$grpsArr[$row['groups']][] = $row;
adds current iteration row to the subarray of the group indicated in $row['groups'].
After fetching the last record from the recordset, the $grpsArr array should look like:
grpsArr = array {
"group_1" => array {
array {
"Kiosk" => "KioskVal_1",
"groups" => "group_1",
"city" => "city_1",
"CBTotal" => 123.45
"BWTotal" => ...
"Payout" => ...
} ,
( ......... ) ,
array {
"Kiosk" => "KioskVal_31",
"groups" => "group_1",
"city" => "city_11",
"CBTotal" => 123.45
"BWTotal" => ...
"Payout" => ...
}
}
( .................... ),
"group_m" => array {
array {
"Kiosk" => "KioskVal_m",
"groups" => "group_m",
"city" => "city_m",
"CBTotal" => 123.45
"BWTotal" => ...
"Payout" => ...
} ,
( .................... ) ,
array {
"Kiosk" => "KioskVal_m2",
"groups" => "group_2",
"city" => "city_mm",
"CBTotal" => 123.45
"BWTotal" => ...
"Payout" => ...
}
}
}
foreach loop
foreach ($grpsArr as $grpName => $grpRowArray) {
echo '<table><tr><th colspan="6">'.$grpName.'</td></tr><tr><th colspan="3">'
.date("m",strtotime($row['date']))
.' Month</th><th>Bet</th><th>Bet-Win</th><th>Payout %</th></tr>';
foreach($grpRowArray as $grpRow) {
echo '<tr><td>'.$grpRow['Kiosk'].'</td><td>'.$grpRow['groups'].'</td><td>'.$grpRow['city'].'</td><td>'.$grpRow['CBTotal'].'</td><td>'.$grpRow['BWTotal'].'</td><td>'.$grpRow['Payout'].'</td></tr>';
}
echo '</table>';
}
The main loop foreach ($grpsArr as $grpName => $grpRowArray) iterates through the first level of $grpsArr table, getting the group name of currently processed group and then builds HTML table start tag with header row for this specific group.
Internal loop foreach($grpRowArray as $grpRow) iterates over the array containing rows that belong to the the currently processed group and builds HTML table row from the obtained data.
There is one problem: you used in your code .date("m",strtotime($row['date'])). for writing the proper date/time for the group. However there is no date field in the results of the last query - nevertheless I've put it also in my code.
This approach should give you one HTML table for each of the groups.
I hope it helps you some way.

Related

Joining two mysql tables and populate an array in php

I have two tables
First table name is "Library"
ID Name
1 A
2 B
Second table name is "Books"
BID Book_Creater Book_Name
1 Variation1 Book1
1 Variation2 Book2
1 Variation3 Book3
2 Variation1 Book4
2 Variation2 Book5
The sql is
$sql = mysql_query("select library.ID,books.Book_Creater,books.Book_name from library,books where library.ID = books.BID;
Result is
ID Book_Creater Book_name
1 Variation1 Book1
1 Variation2 Book2
1 Variation3 Book3
2 Variation1 Book4
2 Variation2 Book5
Now I would like to create an array which should look like and this is where I am stuck.
array(
[1] => array(
[Variation1] => Book1
[Variation2] => Book2
[Variation3] => Book3
)
[2] => array(
[Variation1] => Book4
[Variation2] => Book5
)
)
Any suggestion will do great.
$res = array();
//for each result row
while($row = mysql_fetch_array($sql))
{
//add a row to the multi dimensional result array
//where the first key = id and the second key = Book_Creater
$res[$row['id']][$row['Book_Creater']] = $row['Book_name'];
}
print_r($res);
Simple way is to do a join as you currently do, and push them into an array as you loop around (possibly for neatness creating a new sub array explicitly when the ID as a key doesn't already exist).
Something like this:-
<?php
$store_array = array();
$sql = mysql_query("SELECT library.ID,books.Book_Creater,books.Book_name
FROM library
INNER JOIN books
ON library.ID = books.BID");
$result = mysql_query($sql);
while ($row = mysql_fetch_assoc($result))
{
if (!array_key_exists($row['ID'], $store_array))
{
$store_array[$row['ID']] = array();
}
$store_array[$row['ID']][$row['Book_Creater']] = $row['Book_name']
}
print_r($store_array);
?>
You could also shuffle some effort onto the database and bring things back concatenated together. Then just split the results to put into the array:-
<?php
$store_array = array();
$sql = mysql_query("SELECT library.ID, GROUP_CONCAT(CONCAT_WS('#~#', books.Book_Creater,books.Book_name)) AS details
FROM library
INNER JOIN books
ON library.ID = books.BID
GROUP BY library.ID");
$result = mysql_query($sql);
while ($row = mysql_fetch_assoc($result))
{
$store_array[$row['ID']] = array();
$details = explode(',', $row['details']);
foreach($details as $detail)
{
$detail_line = explode('#~#', $row['detail']);
$store_array[$row['ID']][$detail_line[0]] = $detail_line[1];
}
}
print_r($store_array);
?>
Note that if you are doing this with real data you probably want to chose delimiters which are not going to appear in your data, and also that by default GROUP_CONCAT has a fairly limited max length.
Note also I have used mysql_* functions as that is what you seem to be using, but these are deprecated and probably shouldn't be used now.

Is using PHP to loop a mySQL query efficient?

I have a HTML table full of check-boxes on page 1 with the name attribute set like this:
input type="checkbox" name="A_1"
input type="checkbox" name="B_2"
On the following page, I loop through my $_POST array in PHP with explode to make an array like this:
Array ( [A_1] => on [A_2] => on [B_2] => on [B_5] => on [C_5] => on [submit] => Submit )
Into two arrays:
row_Array = Array ( [0] => 1 [1] => 2 [2] => 2 [3] => 5 [4] => 5 )
column_Array = Array ( [0] => A [1] => A [2] => B [3] => B [4] => C )
This is my SQL query:
for($i=0; $i < count($column_array); $i++) {
$sql = "SELECT {$column_array[$i]} FROM table WHERE num IN ({$row_array[$i]})";
$result = mysqli_query($connection, $sql);
while ($data = mysqli_fetch_assoc($result)) {
$result_array[] = $data[$column_array[$i]];
}
}
Here is an example of my SQL table:
A B C
1 cat cot cet
2 rat rot ret
3 hat hot het
4 lat lot let
5 bat bot bet
The individual SQL queries from my loop look like this and return the correct values:
SELECT A FROM table WHERE num IN (1) returns cat
SELECT A FROM table WHERE num IN (2) returns rat
SELECT B FROM table WHERE num IN (2) returns rot
SELECT B FROM table WHERE num IN (5) returns bot
SELECT C FROM table WHERE num IN (5) returns bet
I am quite new to sql and php. This works but it seems like a terrible way to do this. Any advice or help would be greatly appreciated.
I believe it's a better practice to run a single query and loop through the data returned rather than looping and then running multiple queries.
However, depending on your data structure and application layout, UI, etc, that may not be possible.
I would aim for something like SELECT A,B,C,num FROM table WHERE num IN (1,2,5)
then maybe
foreach($result as $r){
$data[$r['num']] = $r;
}
Let's try just running one query and loop trough it. It's pretty much #Andy Gee 's answer expressed in code.
$cols = implode(',', array_unique($column_array));
$rows = implode(',', array_unique($row_array));
$sql = "SELECT {$cols} FROM table WHERE num IN ({$rows})";
$result = mysqli_query($connection, $sql);
while ($data = mysqli_fetch_assoc($result)) {
//Do your stuff here
}
Something like, it's realy bad idea but..:
$columns = implode(', ', $column_array);
$num_values = implode(', ', $row_array);
$sql = "SELECT {$columns}, num FROM table WHERE num IN ({$num_values})";
$result = mysqli_query($connection, $sql);
while ($data = mysqli_fetch_assoc($result)) {
$result_array[] = $data[$column_array[$i]];
}
Other way is to build one long Query with UNION
SELECT A as value, num FROM table WHERE num = 1
UNION
SELECT A as value, num FROM table WHERE num = 2
UNION
SELECT B as value, num FROM table WHERE num = 2
UNION
SELECT B as value, num FROM table WHERE num = 5
UNION
SELECT C as value, num FROM table WHERE num = 5
returns:
array(
array("num" => 1, "value" => 'cat'),
array("num" => 1, "value" => 'rat'),
...
);

PHP - return SQL GROUP BY as array?

I'm trying to return a MySQL query using GROUP BY as a array.
My table looks like this:
user_id | type
--------------------
1 | test
1 | test
2 | test
1 | hello
1 | helloworld
And my code and query:
$number_of_workouts = array();
$query = mysqli_query(connect(),"SELECT type, COUNT(*) FROM `log` WHERE `user_id` = $user_id GROUP BY type");
$number_of_workouts = mysqli_fetch_assoc($query);
return $number_of_workouts;
This code above isn't returning a array with all types listed, it will only return the number of one type(assuming that $user_id = 1.
How can I return the result of the query as an array?
mysqli_fetch_assoc($query);
fetches 1 row only from the resultset
If you want ALL rows from the resultset, you have to loop for each row and add it to a stack like:
$number_of_workouts = array();
$query = mysqli_query(connect(),
"SELECT type, COUNT(*) AS count
FROM `log`
WHERE `user_id` = $user_id
GROUP BY type"
);
$array = array();
while ($number_of_workouts = mysqli_fetch_assoc($query)) {
$array[$number_of_workouts['type']] = $number_of_workouts['count'];
}
// Now you have all results like you want in the variable array:
print_r($array);
// print count of type test:
echo $array['test'];
Or you try out mysqli_fetch_all() (http://www.php.net/manual/en/mysqli-result.fetch-all.php)
(sorry for many updates)
You are fetching only first record here. Keep the fetching statement in while loop
while($number_of_workouts = mysqli_fetch_assoc($query))
{
echo "<pre>";
print_r($number_of_workouts);
}

Multidimensional array PHP from MYSQL query

I have the following tables in MYSQL:
CommentTable with columns: comment, commenter, datecommented and postid
PostTable with columns: postid, dateposted
I perform this query in php
Select commentTable.comment, commentTable.commenter, commentTable.datecommented, shareTable.postid, shareTable.dateshared from shareTable Left Join commentTable on commentTable.postid = shareTable.postid where shareTable.postid IN ($postidarray) order by shareTable.dateshared desc
where $postid array is an array of post ids.
The problem I have is when i'm trying to sort the query result into a multidimensional array.
I would want to have a multidimensional array called comment which would like this
Comment{
[0] {
[0] => "Comment 1 from first key in $postidaray"
[1] => "Comment 2 from first key in $postidarray"
}
[1] {
[0] => "Comment 1 from second key in $postidarray"
} // assuming there is only one comment for the second key in $postidarray
[2]{
[0] => "Comment 1 from third key in $postidarray"
[1] => "Comment 2 from third key in $postidarray"
[2] => "Comment 3 from third key in $postidarray"
[3] => "Comment 4 from third key in $postidarray"
}
// assuming there are 4 comments for the third key in $postidarray
}
}
I'm doing this so that when I make a php echo I can loop out the comments relating to the specific post
For instance comment[0][1] would echo 'Comment 2 from first key in $postidarray'
Any help is appreciated.
You could do an ORDER BY shareTable.postId THEN BY shareTable.dateshared DESC
This would make all the rows with the same postId appear together so you could just check for a change of postId.
$i=-1;
$currentPostId=0;
$comment = array();
while($assoc = mysql_fetch_assoc($res)){
if($assoc['postId']!=$currentPostId){
$currentPostId = $assoc['postId'];
$i++;
}
$comment[$i][] = $res;
}
This should give you the result you want.
Alternately, If you use PDO, Use a prepared statement instead of using a single query with IN( ... )
$stmt = $pdo->prepare("Select ... shareTable.postid=? order by ShareTable.dateshared desc");
$comment = array();
$p = &$postIds[0];
$stmt->bindParam($p);
foreach($postIds as $p){
$stmt->execute();
$comment[] = $stmt->fetchAll(PDO::FETCH_ASSOC);
}

Cross tabulating a query with php

I'm trying to come up with an efficient way of displaying some data but not succeeding at all.
The table is built dynamically from a few tables to show a row of headers with the columns populated showing the results by site e.g:
Site name | Column A | Column B | Column C => column headers continue from DB query
Site A | Result A | Result B | Result C
Site B | Result C | Result B | Result C
Site C | Result C | Result B | Result C
Results keep going vertically.
Here's the query I'm using
$risk_section=$row_risk_category['risksectid'];
mysql_select_db($database_auditing, $auditing);
$qry_selfsites = sprintf("SELECT
tblself.siteid AS selfsite,
tblsite.sitename AS sitename,
tblsite.address AS address,
tblpct.pctname AS pctname,
tblresultsnew.total,
tblresultsnew.auditid AS auditid,
tblriskcategories.risksectid AS risksectid,
tblriskcategories.risksection AS risksection
FROM tblself
LEFT JOIN tblresultsnew ON tblself.auditid = tblresultsnew.auditid
LEFT JOIN tblsite ON tblself.siteid = tblsite.siteid
LEFT JOIN tblpct ON tblsite.pctid = tblpct.pctid
LEFT JOIN tblriskcategories ON
tblresultsnew.risksectid=tblriskcategories.risksectid
WHERE tblsite.pctid IN (SELECT pctid FROM tblreportpcts WHERE
pctreportid='$pctreportid')
AND tblsite.sitetypeid IN (SELECT sitetypeid FROM tblreportsites WHERE
pctreportid='$pctreportid')
AND tblself.year = %s
ORDER BY tblsite.pctid,tblsite.sitename",
GetSQLValueString($yearofrpt, "int"));
$selfsites = mysql_query($qry_selfsites, $auditing) or die(mysql_error());
$totalRows_selfsites = mysql_num_rows($selfsites);
So the question is, is there a way to get the data from the above query (or an adapted version thereof) to build the table dynamically with all the results lining up correctly?
So far, I can only get it to build vertically.
Sorry, edit time (having worked with the answer below, I realised I hadn't got the question worded very well)
What I'm trying to get is a row of column headers from the query (tblriskcategories.risksection AS risksection) These populate horizontally to give the columns names.
Then underneath, the sitename is displayed with the result corresponding to the column header above i.e.
<table>
<tr>
<th>Sitename</th>
<?php while($row_selfsites=mysql_fetch_assoc($selfsites){
//loop through the section headers pulled from the DB (tblriskcategories)
<th><?php echo $row_selfsites['risksection'];//show the section headers?></th>
<?php }
//end header loop then start another loop to show a row for each site pulled
//out by the query and show the relevant results in the correct column
while($row_selfsites=mysql_fetch_assoc($selfsites)) {
//do the vertical drop matching the header rows with the sitenames from tblsite
//and the results from tblresultsnew
?>
<tr>
<td><?php echo $row_selfsites['sitename'];?></td>
<td><?php echo $row_selfsites['total'];
//these need to grow to fit the headers and each site?></td>
<tr>
<?php } //end displayed data loop?>
</table>
The relevant tables structure below:
tblresultsnew resultsid,auditid,risksectid,total
tblriskcategories risksectid, risksection
tblself selfauditid,siteid,auditid
tblsite siteid,sitename
So tblself holds the list of sites we need the data for and the relevant auditid,
tblresultsnew holds the results - the total column - for each risksectid and each auditid eg, one auditid can have approx 8 risksectid's each with corresponding total
tblriskcategories holds the column headings
tblsite holds the site data to make it mean something
I hope this explains the question a little further.
Thanks again for all the help.
Dave
$rows = array(
0 => array('headingA' => 'results1a', 'headingB' => 'results1b', ),
1 => array('headingA' => 'results2a', 'headingB' => 'results2b', ),
2 => array('headingA' => 'results3a', 'headingB' => 'results3b', ),
);
// $rows is spoofing a db result set as an array
//var_dump( $rows );
$first = true ;
$header_row = "START TABLE <br />" ;
$data_rows = "";
foreach( $rows as $row ) {
foreach( $row as $key=>$value ){
if( $first === true ){
$header_row .= "$key | ";
}
$data_rows .= "$value |";
}
if( $first ) $header_row .="<br />";
$data_rows .= "<br />";
$first = false;
}
echo $header_row . $data_rows . "END TABLE";
Gives:
START TABLE
headingA | headingB |
results1a |results1b |
results2a |results2b |
results3a |results3b |
END TABLE
Is that the kind of solution you are after?

Categories