Mysql count column issue - php

I can't figure-it out how to count all these dancers columns and echo with total of all dancers
id | dancer1 | dancer2 | dancer3 | dancer4, and so on..
---------------------------------------
1 alex michael dalm name
2 clare rose test
I have this for the start but is not working:
$counter = mysql_query("SELECT COUNT(*) AS id FROM table");
$num = mysql_fetch_array($counter);
$dancers = $num["id"];
echo "Total dancers: $dancers";
Any help is appreciated. Thanks!

Try this:
$counter = mysql_query("SELECT * FROM table");
$dancers = 0;
while($rows = mysql_fetch_array($counter)){
for($i = 1; $i <= 24; $i++){
$dan_id = 'dancer'.$i;
if($rows[$dan_id] != "" || $rows[$dan_id] != null )
$dancers++;
}
}
echo "Total dancers:". $dancers;
Note: Never design your database table like this.

I would actually save your dancers in a different (easier) way... For examle:
ID NAME SURNAME PHONE ....
1 Anna Brickstone 0975 ...
2 Jef Damen 0754 ...
That way you could use the following code to count tables:
$dancersCount="0";
$sql = "SELECT * FROM dancers";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
$dancersCount++;
}
} else {
echo "No dancers..";
}
echo"$dancersCount";
The counter will count +1 each time it finds a row (dancer)
If you really want to do it that way...
Then I don't really think there's an easy way to fix this... You will probably need to check how many columns you have in your database but that's not something i can help you with...

You need to change your table structure:
id | dancerNumber | name
1 1 alex
2 1 clare
3 2 michael
4 2 rose
5 3 dalm
6 3 test
7 4 name
8 4 dana
SELECT COUNT(*) AS id FROM table will return 8 dancers. If this is what you were looking for?
if you want to keep your structure then you need to do the following sql query
SELECT dancer1,
dancer2,
dancer3,
(CASE WHEN (dancer1 <> "" AND dancer1 IS NOT NULL) THEN 1 ELSE 0 END +
CASE WHEN (dancer2 <> "" AND dancer2 IS NOT NULL) THEN 1 ELSE 0 END +
CASE WHEN (dancer3 <> "" AND dancer3 IS NOT NULL) THEN 1 ELSE 0 END) AS COUNTER
FROM table
This will count all the non empty and non null columns and add a counter at the end of the table. this counter will then contain the number of dancers with your structure.
Full answer with your php code
$query = 'SELECT (CASE WHEN (dancer1 <> "" AND dancer1 IS NOT NULL) THEN 1 ELSE 0 END +
CASE WHEN (dancer2 <> "" AND dancer2 IS NOT NULL) THEN 1 ELSE 0 END +
CASE WHEN (dancer3 <> "" AND dancer3 IS NOT NULL) THEN 1 ELSE 0 END) AS COUNTER
FROM table'
$counter = mysql_query($query);
$num = mysql_fetch_array($counter);
$dancers = $num["COUNTER"];
echo "Total dancers: $dancers";

Related

Limit number of results using column value as a count

I have two queries, one which will get a list of IDs from the main table, and another which will get all records in another table that relate to that ID.
I'd like to split it into pages of results, but my google searches are only coming up with people who want to have a certain number of results per column value, not who want to limit the overall count by it.
The main table has a column that contains the number of records, so actually reading the other table isn't needed. The limit would be used as a minimum value, so if there are still records left in the current group after the limit, it'll continue displaying them. That'd be somehow calculated as part of the offset so it can start in the correct place.
Here's an example of what I mean:
Table 1:
ID | Records
1 | 2
2 | 3
3 | 28
4 | 7
...
Table 2 (contents don't need to be known for this question):
ID | GroupID | Value
1 | 1 | x
2 | 1 | x
3 | 2 | x
4 | 2 | x
5 | 2 | x
6 | 3 | x
...
If the limit was given as 3 for example, both 1 and 2 should display on the first page, since just 1 by itself is under the limit. The next page will then start on 3, and that'll take up the entire page.
I could just manually count up using PHP until I reach the limit, though it might end up going slow if there were a lot of pages (I've no idea if mysql would be any better in that regard though). Here's a quick example of how that'd work to get the offset:
$page = 2;
$limit = 40;
$count = 0;
$current_page = 1;
$query = 'SELECT ID, Records FROM table1';
$stmt = $conn->prepare($query);
$stmt->execute();
while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
$count += $row['Records'];
if($count > $limit){
$current_page ++;
$count = 0;
if($current_page == $page){
$start_id = $row['ID'];
break;
}
}
}
Updated:
A "custom" Pagination is what you're looking for. So if you're planning to hop from page to page, you can't use hardcoded $page and $current_page values. Those values should be generated dynamically once you're on a particular page. In fact, you should have the ID column value in the query part of the URL so that the pagination links could satisfy your business logic.
Assuming the fact that your ID column value starts from 1, your code should be like this:
$id = isset($_GET['id']) && is_numeric($_GET['id']) ? $_GET['id'] : 1;
$limit = 40;
// Display query results based on particular ID number
$query = 'SELECT ID, Records FROM table1 WHERE ID >= ' . $id;
$stmt = $conn->prepare($query);
$stmt->execute();
$rowCount = $stmt->rowCount();
if($rowCount){
$total = 0;
while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
if($total <= $limit){
$total += $row['Records'];
// Display $row details here
}else{
// Get the next $id value
$id = $row['ID'];
break;
}
}
}
// Display relevant ID links
$query = 'SELECT * FROM table1';
$stmt = $conn->prepare($query);
$stmt->execute();
$idArr = array();
$total = 0;
while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
if($total == 0){
$idArr[] = $row['ID'];
}
if($total <= $limit){
$total += $row['Records'];
}else{
$total = 0;
}
}
foreach($idArr as $idValue){
if($idValue == $id){
echo '<a>'.$idValue.'</a> ';
}else{
echo ''.$idValue.' ';
}
}
Sidenote: If the ID column value of your table doesn't start from 1, then use a separate query to get the first ID value and update the following statement,
$id = isset($_GET['id']) && is_numeric($_GET['id']) ? $_GET['id'] : <FIRST_ID_VALUE>;
If you only need to create the "Next" button, you could try this way:
select t1.ID, t1.Records
from table1 t1
left join table1 t2
on t2.ID < t1.ID
and t2.ID > :last_selected_id_1
where t1.ID > :last_selected_id_2
group by t1.ID, t1.Records
having coalesce(sum(t2.Records), 0) < :limit
order by t1.ID
:last_selected_id_x is the last ID from the current page or 0 for the first page.
http://rextester.com/FJRUV28068
You can use MySQL session variables to create page links:
select page, min(ID) as min_id, max(ID) as max_id
from (
select ID
, #page := case when #sum = 0 then #page + 1 else #page end as page
, #sum := case when (#sum + Records) >= :limit
then 0
else #sum + Records
end as sum
from table1
cross join (select #sum := 0, #page := 0) initvars
order by ID
) sub
group by page
The result would look like:
page | min_id | max_id
1 | 1 | 2
2 | 3 | 3
3 | 4 | 4
http://rextester.com/LQVJWP18655
Note that it is officially (as of documentation) not recomended to use the session variables like that (read and write in one statement). Feature versions may break your code.
Here's the result I ended up with, I ended up basing it off Rajdeeps answer but tweaked so that it'll allow sorting.
$query = 'SELECT ID, Records FROM table1 ORDER BY something';
$stmt = $conn->prepare($query);
$stmt->execute();
$id_array = array(); // For storing each ID
$current_ids = array(); // For storing the current ID pages
$initial_ids = array(); // For storing the first page, in case the page is too high
$count = 0;
$current_page = 1;
while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
$already_reset = false;
// Move the session to the next page if it's more over the limit than under
// For example, if a limit of 10 has 6 records already, and the next ID is 9 records, then start a new page
if($id_array and $count + $row['Records'] / 2 > $max_links){
array_push($id_array, $last_id);
$current_page ++;
$count = 0;
$already_reset = true; // Set a marker so that if this ID is larger than the limit then don't start a 2nd new page
}
// Backup the first results in case page is too high and needs to be reset to 1
if($current_page == 1){
array_push($initial_ids, $row['ID']);
}
$count += $row['Records'];
// The values that appear here are the results for the selected page
// They may not be in sequence so store the individual IDs
if($_GET['page'] == $current_page){
array_push($current_ids, $row['ID']);
}
// Start a new page if over the limit
if($count > $max_links and !$already_reset){
$current_page ++;
$count = 0;
array_push($id_array, $row['ID']);
}
$last_id = $row['ID'];
}
array_push($id_array, $last_id);
$total_pages = count($id_array);
// If page is invalid revert to default
if(!$current_ids){
$current_ids = $initial_ids;
$_GET['page'] = 1;
}
$_GET['page'] = max(1, min($total_pages, intval($_GET['page'])));
$current_ids is an array of the IDs for the current page, and $total_pages is pretty self explanatory.

FIFO calculation in php (mysql)

I have two data tables stock_incomes, stock_outcomes and stock_outcomes_fifo (the one I insert pre-calculated data):
stock_incomes (stores leftovers data)
id| Levtv
-----------
7 | 100
8 | 250
9 | 350
stock_outcomes (here is the point)
id| Quantity
--------------
1 | 150*
I have no problem when stock_outcomes.Quantity is less than 100 (min(Id) from stock_incomes, please see my code below) but I have no idea what code to write I could get calculations if outcome is >100. In my example I used 150 and I would like to get data in next table as:
stock_outcomes_fifo (the one I wish to insert pre-calculated data from the previous two tables)
id| IncomeId| OutcomeId| OutcomePart| Leftv
---------------------------------------------
1 | 7 | 1 | 100 | 0
2 | 8 | 1 | 50 | 200
Here is my code with question inside (see last part of the code):
<?php
include_once("config.inc.php");
include_once("db.class.php");
// stock_outcomes
$db = new db($host, $database, $user, $passwd);
$sql = "SELECT * FROM stock_outcomes WHERE Id = '1'";
$mas = $db->get_array($sql);
if($mas) {
foreach ($mas as $k => $v) {
$OutcomeId = $mas[$k]['Id'];
$OutcomeQuantity = $mas[$k]['Quantity'];
}
}
// stock_incomes
$sql = "select * from stock_incomes where Id = (select min(Id) from stock_incomes where Leftv > 0)";
$mas = $db->get_array($sql);
if($mas) {
foreach ($mas as $k => $v) {
$IncomeId = $mas[$k]['Id'];
$IncomeLeftv = $mas[$k]['Leftv'];
}
}
// insert into stock_outcomes_fifo
if ($OutcomeQuantity <= $IncomeLeftv) {
$OutcomePart = $OutcomeQuantity;
$FifoLeftv = $IncomeLeftv - $OutcomeQuantity;
mysql_query("INSERT INTO `stock_outcomes_fifo` (IncomeId,OutcomeId,OutcomePart,Leftv) VALUES ($IncomeId, $OutcomeId, $OutcomePart, $FifoLeftv)");
}
if ($OutcomeQuantity > $IncomeLeftv) {
// I have no idea what php function to use in this case... please give me direction, thank you...
}
?>
The question has been solved, here is the final working code in case someone might need it:
<?php
include_once("config.inc.php");
include_once("db.class.php");
// stock_outcomes
$db = new db($host, $database, $user, $passwd);
$sql = "SELECT * FROM stock_outcomes WHERE Id = '1'";
$mas = $db->get_array($sql);
if($mas){
foreach ($mas as $k=>$v) {
$OutcomeId=$mas[$k]['Id'];
$OutcomeBarCode=$mas[$k]['BarCode'];
$OutcomeQuantity=$mas[$k]['Quantity'];
}
}
/* - Start code */
if ($OutcomeQuantity > 0) {
$sql = "select * from stock_incomes where Leftv > 0 order by id asc";
$mas = $db->get_array($sql);
if ($mas) {
//filing stock_outcomes_fifo
foreach ($mas as $k=>$v) {
$IncomeId = $mas[$k]['Id'];
$IncomeQuantity = $mas[$k]['Quantity'];
$IncomeUnitPrice = $mas[$k]['UnitPrice'];
$IncomeLeftv = $mas[$k]['Leftv'];
$OutcomePart = min($OutcomeQuantity, $IncomeLeftv);
$FifoLeftv = $IncomeLeftv - $OutcomePart;
$FifoCost = $IncomeUnitPrice * $OutcomePart;
mysql_query("INSERT INTO `stock_outcomes_fifo` (BarCode,IncomeId,OutcomeId,OutcomePart,UnitPrice,Leftv,Cost) VALUES ($OutcomeBarCode, $IncomeId, $OutcomeId, $OutcomePart, $IncomeUnitPrice, $FifoLeftv, $FifoCost)");
mysql_query("UPDATE `stock_incomes` SET Leftv = ".$FifoLeftv." WHERE Id = ".$IncomeId);
$OutcomeQuantity -= $OutcomePart;
if ($OutcomeQuantity <= 0) break;
}
$OutcomeCostQuery = "select sum(Cost) as summ from stock_outcomes_fifo where OutcomeId = ".$OutcomeId."";
$OutcomeCost = mysql_query($OutcomeCostQuery);
$OutcomeCostResult = mysql_fetch_array($OutcomeCost);
mysql_query("UPDATE `stock_outcomes` SET Cost = ".$OutcomeCostResult["summ"]." WHERE Id = ".$OutcomeId."");
}
} /* - Finish code */
?>
Please help me let me explain with this.....
purchase table
id purchase_id product_id qty net_unit_cost created_at
-------------------------------------------------------------------------
1 1 1 10 10 2022-10-10
--------------------------------------------------------------------------
2 2 1 20 12 2022-10-10
Sale table
sale_id product_id qty net_unit_price created_at
1 1 11 15 2022-10-10
in this, if i sold '11' units then how can i subtract from the rows to get remaining units? i've to subtract '10' units from first row and '1' unit from second row...

how can I get row number via php/mysqli

id state
1 1
2 0
5 1
4 0
7 1
I want first remove all state=0 form my result. and then return row number of target record.
for example for id='7' it must return me 3
how can I do it with mysqli/php?
this is false but something like this:
function getLogs($itime = 0,$count = null)
{
$conn = $this->connectDB();
$sql = "SELECT num_rows() FROM Content Where id='22' and $state=0 ORDER BY id ASC";
$rows = mysqli_fetch_all($conn->query($sql), MYSQLI_ASSOC);
$this->disconnectDB($conn);
return num_rows();
}
This is probably simpler and you can replace 22 with a variable.
SELECT COUNT(id) FROM Content WHERE id <= 22 AND state != 0
In your example you put 22 in quotes, but your id isn't a string is it? Plus in addition to the comment above about $state = 0, it should be state not $state

Update numbers in table with variable and update variable

As you can see from the table below the user with the id of 1 has 10 points altogether
What I'm trying to do is have one number submitted from a form $edit_points to loop through and subtract from user 1
This number could be anything eg:
$edit_points = 6
would subtract 4 from the first record
then move to the next and only subtract the remainder 2
then break out of loop
UserID | TotalPoints
-------------------
1 | 4
1 | 4
1 | 2
4 | 3
3 | 3
5 | 4
This is what I've got so far
$pointLeft = $edit_points;//sent from form
while($point = mysqli_fetch_array($output)){
if($pointLeft > $point["TotalPoints"]){//if pointsLeft more than this record
$remainder = $pointLeft-$point["TotalPoints"];//get remainder
$query2 = "UPDATE pointstable SET TotalPoints=0 WHERE UserID=".$UserID;
$output2 = $mysqli->query($query2);
}elseif($pointLeft < $point["TotalPoints"]){
$remainder = $point["TotalPoints"] - $pointLeft;
$query2 = "UPDATE pointstable SET TotalPoints=".$remainder." WHERE UserID=".$UserID;
$output2 = $mysqli->query($query2);
}
$pointLeft = $remainder;
}
It works to a point and seems to populate all the records with the same last value that remainder holds
I've tried break and putting an if ($pointLeft<=0) above the first if
but none works.
any help? or a better way of doing it preferably using php
Thanks to Marty
Revised code below
There's a unique id PointID that I now use
$poinstLeft = $edit_points; //sent from form
while($point = mysqli_fetch_array($output)){
//if pointsLeft more than this record
if($poinstLeft >= $point["TotalPoints"]){
//get remainder
echo $poinstLeft." ";
$remainder = $poinstLeft-$point["TotalPoints"];
$query2 = "UPDATE pointstable SET TotalPoints=0 WHERE UserID=".$UserID." AND PointID=".$point["PointID"];
$output2 = $mysqli->query($query2);
// Calculate new pointsleft
$poinstLeft = $remainder;
} elseif ($poinstLeft < $point["TotalPoints"]){
$remainder = $point["TotalPoints"] - $poinstLeft;
echo $poinstLeft." ";
$query2 = "UPDATE pointstable SET TotalPoints=".$remainder." WHERE UserID=".$UserID." AND PointID=".$point["PointID"] ;
$output2 = $mysqli->query($query2);
// Here, your remainder is different from the upper half of your if-function!
// So, you don't have to recalculate pointsleft... It's just:
$poinstLeft = 0;
// Break the while loop:
break 2;
}
}

How to make ranking system in PHP

I have problem. .
In my case i make championship. . You know, the winner is determined by the highest value. .
Example :
$sql = "SELECT bla bla bla FROM `user` ORDER BY `point` DESC";
$result = mysql_query($sql);
$i=0;
while($row = mysql_fetch_array($result)) {
$1++;
echo "rank ".$i." is ".$row['name']." with point ".$row['point'].";
}
It's will show
rank 1 is abc with point 10
rank 2 is def with point 9
rank 3 is ghi with point 8
rank 4 is jkl with point 7
rank 5 is mno with point 7
rank 6 is pqr with point 3
rank 7 is stu with point 1
The question. .
look the result. . rank 4 and rank 5 have same point. . how to make
they in same possition ??
how to auto detect title of champions like rank 1 is the big boss, rank 2 is a boss, rank 7 is worker ??
how to tell ex: you in possition 6 ??
$sql = "SELECT bla bla bla FROM `user` ORDER BY `point` DESC";
$result = mysql_query($sql);
if( !$result ){
echo 'SQL Query Failed';
}else{
$rank = 0;
$last_score = false;
$rows = 0;
while( $row = mysql_fetch_array( $result ) ){
$rows++;
if( $last_score!= $row['point'] ){
$last_score = $row['point'];
$rank = $rows;
}
echo "rank ".$rank." is ".$row['name']." with point ".$row['point'].";
}
}
This code will also adjust the rankings properly - such as:
rank 1 is Adam Aarons with point 100
rank 2 is Barry Blue with point 90
rank 2 is Betty Boop with point 90
rank 4 is Charlie Chaplin with point 80
Note that there is no "rank 3", as "Charlie Chaplin" is actually the fourth-highest scorer.
If you do not want this behaviour, then simply replace $rank = $rows; with $rank++;
ad 1. group by point, add #curRow := \#curRow + 1 AS row_numbe to select the current row number which will be the rank position
ad 2. left join title_dict on row_number = title_dict.id
where title dictionary is table with title_id and title name dictionary
ad 3. select from your select on id = your id
Actually, a very easy way to order players with same amount of points is to add a column "points_last_update" containing the timestamp of the last update to the "points" column. Then you just add the "points_last_update" to the ORDER BY in your sql statement. That way, the player who has reached the points the first gets the higher ranking, wich is logic.
Save the last score and make sure it does not equal the current score before you increment.
$sql = "SELECT bla bla bla FROM `user` ORDER BY `point` DESC";
$result = mysql_query($sql);
$i=0;
$lastscore = NULL;
while($row = mysql_fetch_array($result)) {
if ($lastscore != $row['point']){
$i++;
}
echo "rank ".$i." is ".$row['name']." with point ".$row['point'];
$lastscore = $row['point'];
}

Categories