While in a while display only one row? - php

I have two SQL table, one contains "manual inserted datas" and the other one "automatic inserted data" by script.
In order to test if the script works well, the manual table and the auto table are the same.
So, I would like to "compare" both database, and then in another script, highlight the difference.
// $currentdate_today_midnight is a timestamp
$sql_getLive = "SELECT * FROM worksheets WHERE entry_date > $currentdate_today_midnight";
$req_getLive = $cnx->query($sql_getLive);
$req_getLive->setFetchMode(PDO::FETCH_OBJ);
// countAll counts all rows for a table and a condition
$countLive = countAll("worksheets", "entry_date > $currentdate_today_midnight");
$sql_getCriter = "SELECT * FROM criter_live WHERE entry_date > $currentdate_today_midnight";
$req_getCriter = $cnx->query($sql_getCriter);
$req_getCriter->setFetchMode(PDO::FETCH_OBJ);
$countCriter = countAll("criter_live", "entry_date > $currentdate_today_midnight");
if($countLive == 0){
/* If there is no live (manual datas) inserted */
echo "EMPTY";
die();
}
while ($check_criter = $req_getCriter->fetch()) {
while ($check_live = $req_getLive->fetch()) {
if ($check_live->train_id == $check_criter->train_id) {
/* check_live = worksheets */
/* check_criter = criter_live */
echo $check_live->train_id . "|" . $check_criter->entry_date . "|" . $check_live->entry_date . "|". $check_criter->left_date . "|". $check_live->entry_date . "|". $check_criter->train_type . "|". $check_live->train_type . "|". $check_criter->entry_number . "|". $check_live->entry_number . "|". $check_criter->left_number . "|". $check_live->left_number. "#";
}
}
}
So, I've tried to make "a while in a while" but it doesn't work, I get only one "echo"... instead of 17 (returned thanks to the countAll function).
Did I made a mistake? Or is there any other solution?
Thank you!

perhaps you could try to find the differences directly in the sql like this:
select * from `worksheets` where `entry_date` > $currentdate_today_midnight
and `train_id` not in (
select `train_id` from `criter_live` where `entry_date` > $currentdate_today_midnight
)
A slightly modified version, testing entry_date
select * from `worksheets` where `entry_date` > $currentdate_today_midnight
and `entry_date` not in (
select `entry_date` from `criter_live` where `entry_date` > $currentdate_today_midnight
)

EDIT: I am assuming you have the same data in both tables.
Remove second while loop:
while ($check_criter = $req_getCriter->fetch()) {
$check_live = $req_getLive->fetch();
if ($check_live->train_id == $check_criter->train_id) {
echo $check_live->train_id . "|" . $check_criter->entry_date . "|" . $check_live->entry_date . "|". $check_criter->left_date . "|". $check_live->entry_date . "|". $check_criter->train_type . "|". $check_live->train_type . "|". $check_criter->entry_number . "|". $check_live->entry_number . "|". $check_criter->left_number . "|". $check_live->left_number. "#";
}
}
Basically, in the first iteration of your outer loop you've been fetching 1 row from $req_getCriter and comparing it to all other rows from $req_getLive. Second iteration wouldn't work, since all rows from $req_getLive were fetched.

After the first iteration of your outer loop, you will have fetched all items in the inner loop from the database result set so it will never run again.
You could of course fetch all items from both queries in arrays and use foreach loops or reset the database cursor for your inner loop, but you could probably do this in one database query as well.

The answer by akasummer will work fine if the sequence of train_id is same in both the tables. If the sequence is not same some rows may be missed.
and if there is no difference in the sequence of train_id in both the tables there is no need of if conditioned in akasummer's answer.
if ($check_live->train_id == $check_criter->train_id)
The easy way to do it my inner join in mysql fetching data from both table on the basis of train_id and there entry dates. As shown below(There can be some silly mistake in syntax, but logic is understandable)
SELECT
W.*,
CL.entry_date AS cl_entry_date,
CL.left_date AS cl_left_date,
CL.train_type AS cl_train_type,
CL.entry_number AS cl_entry_number,
CL.left_number AS cl_left_number
FROM
worksheets AS W,
criter_live AS CL
WHERE
W.train_id = CL.train_id
AND
W.entry_date > $currentdate_today_midnight
AND
CL.entry_date > $currentdate_today_midnight
In one result you will get columns for both the table and then you can check it with a simple plain while loop.

Related

Using while loop to output data of a specific id in same table row

I'm thinking I need to use a while loop within a while loop, but when I do I receive bizarre results.
I have the following PHP:
$sql = "SELECT c.id, c.title, c.image, u.profileImage, u.fname, u.lname, u.level AS ulevel, u.city, u.state, u.hs, u.ps, uc.id, uc.cid
FROM c, u, uc
WHERE uc.cid = c.id AND uc.userid = u.id
ORDER BY usercollege.createdate ASC";
if ($result = mysqli_query($conn, $sql)) {
while ($row = mysqli_fetch_assoc($result)) {
if ($row['status'] == null) {
echo "";
}
if ($row['ulevel'] == "A Profile") {
echo '<tr>' .
'<td class="small">' . '<a href="http://www.example.com/aprofile.php?user="'.$row["username"] . '>' . '<img src="'.$row['profileImage'].'" />' . '</a>' . '</td>' .
'<td class="large">' . $row['fname']. ", " . $row['lname'] . '</td>' .
'<td class="large">' . $row['city'] . ", " . $row['state'] . '</td>' .
'<td class="large">' . $row['hs'] . '</td>' .
'<td class="largest">' .
'<div class="Limage">' . '<img src="images/c/'.$row['image'].'"/>' . '</div>' .
'</td>' .
'</tr>';
$row['image'] within <div class="Limage"> currently returns just ONE image, but the database can have up to 10 images per userid. Obviously, this loop (if there are more than one image per user) will create a new row for the user with a different image.
I am trying to achieve having all images (up to 10) appear within the same row for the same user, without replicating the same user in the table.
If each row contains identical data, except avatar, You need concatenate rows in query:
SELECT c.id, c.title, GROUP_CONCAT(c.image SEPARATOR ','), u.profileImage, u.fname, u.lname, u.level AS ulevel, u.city, u.state, u.hs, u.ps, uc.id, uc.cid
FROM c, u, uc
WHERE uc.cid = c.id AND uc.userid = u.id
GROUP BY c.id
ORDER BY MAX(usercollege.createdate) ASC
Then your result (image field) contains something like this:
avatar1.png,avatar2.png,avatar3.png,avatar4.png
Now You can explode sql-result and show in foreach loop.
while your question is a bit hard to follow I can tell you what you need to do, which is not a loop within a loop ( even though it is ). So because I don't care to decider you schema but I think I understand your issue, i'll outline it with psudo code
First you need to organize your data
if ($result = mysqli_query($conn, $sql)) {
$users = []; //initialize variable to store data in.
while ($row = mysqli_fetch_assoc($result)) {
if( !isset( $users['u'.$row['id']]){
$users['u'.$row['uid']] = $row; //group users by id
}
$users['u'.$row['uid']]['images'][] = $row['image'];
}
//*note you'll have to probably add u.id as uid to you select.
foreach( $users as $user ){
//... code/html for displaying user (open).
foreach( $user['images'] as $img){
//... code/html for displaying image.
}//end foreach image
//... code/html for displaying user (close).
}//end foreach user
What you wind up with for the $users array is something like this when you output it with var_export() etc.
[
[ 'u10' => [
'id' => 10,
'images' => [
'{src for image1}',
'{src for image2}',
]
]
When you pull the records with the join you get a reflection of the one to many relationship users have to images. So you have the same user row for each image row. All you need to do is group them by user id, and that will make your code down stream much easier. Unless your dealing with 1000's of users it will probably have minimal impact on the time, and is well worth it to simplify the HTML structuring. The order they are returned in the sql could be causing all kinds of issues, you could start with user 1 have 10 other users then end with user 1, this way they are grouped nicely in the first loop. To group them we can rely on the fact that associative keys in PHP are unique.
I add the u{id} there because certain PHP functions have a way of resting numeric keys, that just avoids that becoming an issue. Most the time it's not needed, but it's precautionary and takes little effort, makes the array a bit easier to read and IMO a good habit.
Lastly if I recall correctly in CSS, an id of id="10" ( #10{ ..no dice.. } ) is not valid but one of id="u10" is. A bit of an explanation on that can be found here
https://css-tricks.com/ids-cannot-start-with-a-number/
You can add order by uc.userid (and others) so in result array users will have all their raws closely. After that in your while loop u can check if userid changed - then its a new user.

Mysql join returns results in multiple rows instead of one for every instance

I have three tables: tbl_days, tbl_slots and tbl_bookings as follows.
Customers are supposed to book for a slot in a day.
Am using the following query:
$slots = $this->common->slots();
if ($slots != NULL) {
foreach ($slots as $C):
$start = $C->start;
$stop = $C->stop;
$slotspace= $start." to ".$stop;
$available='Available';
$booked ='Booked';
$sum_col[] = " IF(tbl_bookings.slot_id =". $C->id.",'".$booked."','".$available."') AS '" . $slotspace . "'";
endforeach; }
$sqlquery = $this->db->query("SELECT tbl_days.date_day,
" . implode(",", $sum_col) . "
FROM tbl_days
LEFT JOIN tbl_bookings ON tbl_bookings.date = tbl_days.date_day
LEFT JOIN tbl_slots ON tbl_slots.id = tbl_bookings.slot_id
LEFT JOIN tbl_fields ON tbl_fields.id = tbl_bookings.field_id
");
return $sqlquery->result();
However, the results display as:
Intended result should be:
Please note how booking information displays on multiple rows for the same date.
Dates to be from the date today (for the next 7 days from today)
Display slots for the day on one row.
Display the date regardless of if there is a booking or not, like in date 29th.
Kindly help me on how to go about this.
Please note that am using datatables.
So each entry gets displayed in a new row instead of everything that's connected to each other in 1 row, right? I had the same problem in the past and the solution is a second foreach. The second one should look at all the records and see if one is connected to another.
See my question: Each value is displayed in a new row HTML table

merge statement temporary table - how to direct data into a local array?

We're having a tough time debugging because our retired predecessor has a query statement that puts pulled data into a series of temporary tables before uploading to the database. It's not working now (we added items to TestPatterns table, and running for tp7 instead of tp21 so data may differ) and we're having a tough time debugging it. If we could somehow print or access the data put in the temporary tables, maybe we could debug it better. Any ideas on how to debug this better, and maybe see the data? We can print our first select/where statement, but not the data it pulls when the qry is executed. Plus there's the Source/Target sql merges we do. We know everything seems to work until we execute the $qry1d.
I looked online for how to view this info, and see the sql profiler, but I'm worried the statements are too complex to decipher the profiler output. When I tried to profile withhttp://youtu.be/mJ8Dyv4Uk6E, for a simple select top 1000 rows, it said:
exec sp_executesql N'SELECT
clmns.name AS [Name]
FROM
sys.tables AS tbl
INNER JOIN sys.all_columns AS clmns ON clmns.object_id=tbl.object_id
WHERE
(CAST(clmns.is_sparse AS bit)=#_msparam_0)and((tbl.name=#_msparam_1 and SCHEMA_NAME(tbl.schema_id)=#_msparam_2))
ORDER BY
clmns.column_id ASC',N'#_msparam_0 nvarchar(4000),#_msparam_1 nvarchar(4000),#_msparam_2 nvarchar(4000)',#_msparam_0=N'0',#_msparam_1=N'Measurements',#_msparam_2=N'dbo'
It's failing with
The MERGE statement attempted to UPDATE or DELETE the same row more
than once. This happens when a target row matches more than one source
row. A MERGE statement cannot UPDATE/DELETE the same row of the target
table multiple times. Refine the ON clause to ensure a target row
matches at most one source row, or use the GROUP BY clause to group
the source rows.
This is a couple of the php sql merge statements:
$qry = 'SELECT "PrintSamples"."PrintSampleID", "PrintSamples"."TestPatternName", "PrintSamples"."PrintCopyID",
"DigitalImages"."CaptureTime", "PrintSampleAnalyses"."psaTicket", "Measurements"."MeasurementID", "Measurements"."MeasurementUuid",
SUBSTRING("OperatorLastName",1,1) AS "lastInitial", SUBSTRING("OperatorFirstName",1,1) AS "firstInitial",
"ParameterValues"."ParameterID", "ParameterName", "TargetName", "ParameterValues"."ParameterValue"
FROM "ParameterValues"
LEFT JOIN "Measurements" ON "ParameterValues"."MeasurementID"="Measurements"."MeasurementID"
LEFT JOIN "PrintSampleAnalyses" ON "PrintSampleAnalyses"."psaID"="Measurements"."psaID"
LEFT JOIN "DigitalImages" ON "DigitalImages"."ImageID"="PrintSampleAnalyses"."ImageID"
LEFT JOIN "PrintSamples" ON "DigitalImages"."PrintSampleID"="PrintSamples"."PrintSampleID"
LEFT JOIN "Sessions" ON "Sessions"."SessionID"="PrintSampleAnalyses"."SessionID"
LEFT JOIN "Operators" ON "Operators"."OperatorID"="Sessions"."OperatorID"
LEFT JOIN "ParameterNames" ON "ParameterNames"."ParameterID"="ParameterValues"."ParameterID"
LEFT JOIN "Targets" ON "Targets"."TargetID"="Measurements"."TargetID"
WHERE (';
//----------------------------------------------------------------------------------------------------
// The two statements where added to make AvgGhostValAsSir77 and MaxNegGhostingValAsSir77 work.
// After much testing it was found that the query did not recognize these to ParameterNames in the
// Postgres database. It was never discovered why when testing the ParameterName to be equal to
// AvgGhostValAsSir77 or MaxNegGhostingValAsSir77 the query fails but using the LIKE statement
// corrected the problem. It is possible that the names contain a hidden character or space that
// caused the proble. More investigation will need to be done to find a better resolution to this
// strange problem. On 8/1/13 - It was found that the two Parameters AvgGhostValAsSir77 and MaxNegGhostingValAsSir77
// have a trailing space to thier names in the Postgres database and that's why these two parameters
// were NOT working. It was decided instead of having IQAF people modify the database that the two
// statements using the LIKE will remain in place. The file was modified on this date 8/1/13.
//----------------------------------------------------------------------------------------------------
// only take values that actually get reported on the dashboard
// this list comes from the "MeasurementNames" table
foreach ($measurementIDs as $mid){
if($mid[0] == "AvgGhostValAsSir77") $qry .= '(("ParameterName" LIKE ' . "'%AvgGhostValAsSir77%'" . ') AND ("TargetName"=' . "'" . $mid[1] . "')) OR ";
else if($mid[0] == "MaxNegGhostingValAsSir77") $qry .= '(("ParameterName" LIKE ' . "'%MaxNegGhostingValAsSir77%'" . ') AND ("TargetName"=' . "'" . $mid[1] . "')) OR ";
else $qry .= '(("ParameterName"=' . "'" . $mid[0] . "'" . ') AND ("TargetName"=' . "'" . $mid[1] . "')) OR ";
}
$qry = substr ($qry, 0, -4);
$qry .= ") ";
if (isset($captureTime)){ // used for incremental updates
$qry .= ' AND ("CaptureTime">' . "'" . $captureTime . "')";
}
// steve invalid reading code is -99999.
$qry .= ' AND ("ParameterValues"."ParameterValue" != -99999) ORDER BY "PrintSampleID", "MeasurementID"';
$actionString = '$action';
$qryCreate = "CREATE TABLE #tmpMeasurementTable (TestGUID uniqueidentifier,
IQAFid uniqueidentifier, pqID int, MeasurementID int,
EvaluationDate datetime, EvaluatorID int,
TestUnitID int, TestUnitCountID int,
TestPatternID int, ColorID int,
TargetID int, ParameterID int,
ParameterValue real)
CREATE TABLE #MergeOutput (ActionType nvarchar(10))";
//start putting data into measurement tables
$qry1a= "INSERT INTO #tmpMeasurementTable VALUES ";
//put 1a data in MeasurementData
$qry1b = "
MERGE INTO MeasurementData AS Target
USING #tmpMeasurementTable AS Source
ON Target.pqID=Source.pqID
AND Target.MeasurementID=Source.MeasurementID
AND Target.TargetID=Source.TargetID
AND Target.ParameterID=Source.ParameterID
AND Target.TestPatternID=Source.TestPatternID
AND Target.IQAFMeasurementID=Source.IQAFid
WHEN MATCHED THEN
UPDATE SET Target.ParameterValue = Source.ParameterValue,
Target.TestUnitID=Source.TestUnitID,
Target.TestUnitCountID=Source.TestUnitCountID,
Target.EvaluationDate=Source.EvaluationDate,
Target.EvaluatorID=Source.EvaluatorID
WHEN NOT MATCHED BY Target THEN
INSERT (TestGUID, IQAFMeasurementID, pqID,
MeasurementID, EvaluationDate, EvaluatorID,
TestUnitID, TestUnitCountID, TestPatternID, ColorID,
TargetID, ParameterID, ParameterValue)
VALUES (Source.TestGUID, Source.IQAFid, Source.pqID,
Source.MeasurementID, Source.EvaluationDate, Source.EvaluatorID,
Source.TestUnitID, Source.TestUnitCountID,
Source.TestPatternID, Source.ColorID,
Source.TargetID, Source.ParameterID, Source.ParameterValue)
OUTPUT
$actionString INTO #MergeOutput;
DROP TABLE #tmpMeasurementTable";
$qryOutput = "SELECT ActionType, COUNT(ActionType)AS [count] FROM #MergeOutput GROUP BY ActionType";
$qryCleanup = "DROP TABLE #MergeOutput";
$qry1c = "IF EXISTS (SELECT * FROM tempdb.dbo.sysobjects WHERE ID = OBJECT_ID(N'tempdb..#MergeOutput') AND xtype='U')
DROP TABLE #MergeOutput
CREATE TABLE #MergeOutput (ActionType nvarchar(10))
SELECT TestIndex AS TestID, TestID AS TestNumber, MeasurementData.TestGUID, pqID, TestUnitID, TestUnitCountID, TestPatternID,
ColorID, MeasurementData.MeasurementID, TargetID, ParameterID,
CAST(ROUND(AVG(ParameterValue*Multiplier), 2)AS DECIMAL(18,2)) AS Value
INTO #tmpTable
FROM MeasurementData
LEFT JOIN Measurements ON Measurements.MeasurementID=MeasurementData.MeasurementID
LEFT JOIN Tests ON Tests.TestGUID=MeasurementData.TestGUID AND Tests.PiggybackID IS NULL
WHERE MeasurementData.TestGUID='" . $TestGUID . "' AND pqID>=" . $startPQid . " AND pqID<=" .$endPQid;
if (isset($captureTime)) // used for incremental updates
{
$qry1c .= " AND EvaluationDate>'" . makeDateTime($captureTime) . "'";
}
$qry1c .= " GROUP BY TestIndex, TestID, MeasurementData.TestGUID, pqID, TestUnitID, TestUnitCountID, TestPatternID,
ColorID, MeasurementData.MeasurementID, TargetID, ParameterID
ORDER BY ColorID, TestPatternID, TestUnitCountID, MeasurementData.MeasurementID, TargetID, ParameterID;
SELECT ##ROWCOUNT AS rows INTO #DashboardRows;";
//put temporary table in dashboard table
$qry1d = ";
MERGE INTO DashboardData AS Target
USING #tmpTable AS Source
ON Target.pqID=Source.pqID
AND Target.MeasurementID=Source.MeasurementID
AND Target.TargetID=Source.TargetID
AND Target.ParameterID=Source.ParameterID
AND Target.TestPatternID=Source.TestPatternID
WHEN MATCHED THEN
UPDATE SET Target.ParameterValue=Source.Value,
Target.TestUnitID=Source.TestUnitID,
Target.TestUnitCountID=Source.TestUnitCountID
WHEN NOT MATCHED BY Target THEN
INSERT (TestGUID, pqID,
MeasurementID,
TestUnitID, TestUnitCountID, TestPatternID, ColorID,
TargetID, ParameterID, ParameterValue,
TestNumber, TestIndex)
VALUES (Source.TestGUID, Source.pqID,
Source.MeasurementID,
Source.TestUnitID, Source.TestUnitCountID,
Source.TestPatternID, Source.ColorID,
Source.TargetID, Source.ParameterID, Source.Value,
Source.TestNumber, Source.TestID)
OUTPUT
$actionString INTO #MergeOutput;
DROP TABLE #tmpTable";
The queries get executed like this:
$result = $ms_conn->query($qry1c); $recordCount = $ms_conn->fetchOne
("SELECT rows FROM #DashboardRows"); //dataLog ("OLAP database " .
$recordCount . " records to process", true); $result =
$ms_conn->query($qry1d); dataLog ("end dashboard query");
To look at the intermediate tables, remove the first character # from the table names. This will make the tables non temporary, as SQL Server ha the convention that a table is temporary if its name starts with this character. You might also want to remove the drop table statements from the code. Then you can just look into these intermediate tables like into any other table.
Of course, to be able to re-run the code, you would have to drop the tables manually.

MySQL Counting Results Within a Range and First Occurance In Any Range

Looking for some advice on the best way to accomplish this. I've tried Unions, Joins, and Alias examples from a few Stack Overflow questions - none seems to get me where I want to go to no fault of theirs. I think I've just been looking to solve this the wrong way.
I've got one table that logs all activity from our users. Each log contains a column with an ID and another with a TIMESTAMP. There is no column that states what the event type is.
What I'm looking to do is grab counts within a range and append a virtual column with the activation date (first access) regardless if it is in the range or not. The business case for this is that I'd like to have reports that show users active within a range, their activation date, and the amount of events in the range.
The HTML output of this would look like this:
User / Total Visits in the Range / First Visit (in the range or not) / Most Recent Visit (in the range)
How I've gotten this far is by doing this:
$result = mysql_query("
SELECT user, MIN(timestamp), MAX(timestamp), count(user)
AS tagCount FROM " . $table . "
WHERE date(timestamp) BETWEEN '" . $startdate . "' AND '" . $enddate . "'
GROUP BY user
ORDER BY " . $orderby . " " . $order) or die(mysql_error());
I then loop:
$i = 1;
while($row = mysql_fetch_array($result)){
$user_name = str_replace("www.", "", $row['user']); // removing www from usernames
if( $i % 2 != 0) // used for alternating row colors
$iclass = "row";
else
$iclass = "row-bg";
echo "<div class=\"" . $iclass . "\"><div class=\"number\">" . $i . "</div><div class=\"number\">" . $row['tagCount'] . "</div><div class=\"name\">" . "" . $server_name . "" . "</div>" . "<div class=\"first\">" . $row['MIN(timestamp)'] . "</div><div class=\"recent\">" . $row['MAX(timestamp)'] . "</div></div>";
$i++;
}
The MIN(timestamp) in the above grabs the first timestamp in the range - I want to grab the first timestamp regardless of range.
How can I do this?
The key is to create a virtual derived table that calculates their first access separately and then join to it from your query that returns records for the time period you specify.
The below is SQL Server code, but I think it's fine in mysql too. If not, let me know and i'll edit the syntax. The concept is sound either way though.
Just setup code for the sample
if object_id('tempdb..#eventlog') is not null
drop table #eventlog
create table #eventlog
(
userid int ,
eventtimestamp datetime
)
insert #eventlog
select 1,'2011-02-15'
UNION
select 1,'2011-02-16'
UNION
select 1,'2011-02-17'
UNION
select 2,'2011-04-18'
UNION
select 2,'2011-04-20'
UNION
select 2,'2011-04-21'
declare #StartDate datetime
declare #EndDate datetime
set #StartDate = '02-16-2011'
set #EndDate = '05-16-2011'
Here's the code that would solve your problem, you can replace #eventlog with your tablename
select e.userid,
min(eventtimestamp)as FirstVisitInRange,
max(eventtimestamp) as MostRecentVisitInRange,
min(e2.FirstAccess) as FirstAccessEver,
count(e.userid) as EventCountInRange
from #eventlog e
inner join
(select userid,min(eventtimestamp) as FirstAccess
from #eventlog
group by userid
) e2 on e.userid = e2.userid
where
e.eventtimestamp between #StartDate and #EndDate
group by e.userid

Order by Total For Sum function used

<?
$tablae = mysql_query("SELECT * FROM order_history where (type!='rent_referral' AND type!='rental_balance') AND date>'" . strtotime($time1) . "' AND date<'" . strtotime($time2) . "' GROUP BY user_id");
while ($order = mysql_fetch_array($tablae)) {
?>
<tr>
<?
$tablaes = mysql_query("SELECT * FROM members where id='$order[user_id]'");
$user = mysql_fetch_array($tablaes);
$idsd=$user['id'];
$rPaid=mysql_query("SELECT SUM(`price`) AS total FROM order_history WHERE (type!='rent_referral' AND type!='rental_balance') AND date>'" . strtotime($time1) . "' AND date<'" . strtotime($time2) . "'");
$hdPaid = mysql_fetch_array($rPaid);
$sPaid=mysql_query("SELECT SUM(`price`) AS total FROM order_history WHERE user_id='$idsd' AND (type!='rent_referral' AND type!='rental_balance') AND date>'" . strtotime($time1) . "' AND date<'" . strtotime($time2) . "'");
while ($hPaid = mysql_fetch_array($sPaid)) {
?>
<td><?=$user['username']?></td>
<td><?=$hPaid['total']?></td>
<?
}
?>
</tr>
<? } ?>
This gets me this result http://dl.dropbox.com/u/14384295/test.jpeg
I want to order the price totals by DESC.
I would need
$sPaid=mysql_query("SELECT SUM(`price`) AS total FROM order_history WHERE user_id='$idsd' AND (type!='rent_referral' AND type!='rental_balance') AND date>'" . strtotime($time1) . "' AND date<'" . strtotime($time2) . "'");
the total on that to be ordered by DESC.
Be really carefull with GROUP BY instructions in your SQL query. All columns which are in the result and which are not aggregate expressions (expressions would be the count, SUM, max, etc working on the group and not on the rows) should be in your group by expression;
Here you use a select *, you should try to list the real columns instead, and get this list in your group by, or use only SELECT user_id.
Most database would prevent you of running such not-very-well-formted group by query, but MySQl is not bailing you, tthat does not mean he won't gives you completly wrong results if you do not rexpect this rule (all columns which are not aggregates must be in the group by).
Then you should be able to order by an agregate expression by reusing this expression and not his alias in the order clause.
You could either use client side sorting with javascript, there are some nice jQuery addons that can do that.
Or you have to totaly rewrite your code to have a single sql using joins and group by.
But I cannot realy follow the logic with $rPaid, $hPaid and $sPaid so I cannot help you there.

Categories