Only showing lines with more that 20 participants - php

I have a problem i hope you can help me out with.
To break it down, i have a table in the database where i create events, it's called "dansetimer" and for that i have a table called for the participants on the events, called "transak"
I want to count how many events within a given time, had more than 20 participants.
I have made this for a start, and it's also very good, but i cant see how to count, how many events i end up with, of course i can just count the list manually, but i really want to get PHP to count it.
$hentgg = mysql_query("SELECT * FROM dansetimer WHERE dato BETWEEN $fra AND $til");
if(mysql_num_rows($hentgg)) {
while($visgg = mysql_fetch_array($hentgg)) {
$result=mysql_query("SELECT count(*) as total FROM transak WHERE produkt = '$visgg[id]'");
$data=mysql_fetch_assoc($result);
if($data['total'] > 20) {
echo $visgg[title];
}
}
} else {
echo "Ingen resultater";
}
With the above code i'm able to retrieve the events and get them listed.
With this code:
$result=mysql_query("SELECT count(*) as total FROM transak WHERE produkt = '$visgg[id]'");
$data=mysql_fetch_assoc($result);
I can count how many participants there are on the event, and with the if statement, testing if there are more than 20, i can hide the events, that dont have more participants.
But do you have a great idea for how i can write "Within the given time, you held 23 events with more than 20 participants" or something like that.

You could keep an extra counter in the loop, so you can see how many events have over 20 participants:
// At the start of your script
$large_events = 0;
...
// In your loop:
if($data['total'] > 20) {
echo $visgg[title];
$large_events++;
}
But I think it's easier, and probably faster too, to let SQL give you already some more details. In your solution it will query the participants for each event, so if someone has 1000 events, each with 20 participants or less, your database has to do 1001 queries, end the end result is 'Ingen resultater'.
So, change the query to this:
SELECT *
FROM
( SELECT
dt.*,
(SELECT count(*) FROM transak WHERE produkt = dt.id) AS total_participants
FROM dansetimer dt
WHERE dato BETWEEN $fra AND $til
)
WHERE
total_participants > 20
ORDER BY
dato,
title
This query returns only events with more than 20 participant, and it will return the number of participants per event. So you can just fetch this query result into a simple array and display each item to show the title, number of participants and other information. And the length of the array is the number of 'large' events.
PS: Did you know that the mysql_* functions are old and are removed in PHP 7? I think it's time for an upgrade to PDO.

Need to use this below query and you will get desired output (I want to count how many events within a given time, had more than 20 participants.).
SELECT count(*) FROM dansetimer dt WHERE (SELECT count(*) FROM transak WHERE produkt = dt.id)>=20 and dato BETWEEN $fra AND $til

Related

Getting a specific value from my database with an operator

I'm trying to give my users a rank based on the amount of posts they posted. I made a database containing a rankName row with "beginner, novice, itermediate,... to master" and a minimum row with some numbers. I tried to compare the amount of posts ($qtyPosts) with the minimum rows.
For example: When a user has 9 posts, he gets the rank Novice (which has a minimum of 5 posts).
This is the code i wrote for that.
PHP code
// calculate number of posts from user
$rowsPosts = $user->getQuantityOfPosts($userID);
$qtyPosts = 0;
foreach ($rowsPosts as $q) {
$qtyPosts++;
}
//status
$conn = db::getInstance();
$rank = "";
$statementRank = $conn->prepare("SELECT * FROM rank WHERE rank.minimum >= $qtyPosts");
$statementRank->execute();
while($row = $statementRank->fetch(PDO::FETCH_ASSOC) ){
$rank = $row['rankName'];
}
HTML code
<h3>Status: <?php echo $rank; ?></h3>
However, It doesn't post the right rank, instead it posts the latest one, "master". Anyone any idea?
Consider your WHERE clause:
WHERE rank.minimum >= $qtyPosts
If the user is at the lowest rank, then all ranks will be >= that user's post count.
You can keep the same logic, but simply add an order and limit. Something like this:
WHERE rank.minimum >= $qtyPosts ORDER BY rank.minimum LIMIT 1
This would sort the ranks from lowest to highest and just select the first one.
I guess you should have a maximum column as well in the table and change the query to
SELECT * FROM rank WHERE rank.minimum >= $qtyPosts AND rank.maximum < $qtyPosts
Since according to your current post, you'll get all the ranks with $qtyPosts > the minimun number.

Return list of member_number count in table

Consider the following table
I need to return a list in descending order with the count of the member_nr's who is appearing the most frequent in the table where tournament = 'EPL' AND ROUND = '12'
EXAMPLE
The script should return the following results:
I thought about the problem and my logic for the problem reads like this
STEP1: GET member_nr one by one
$sql = "SELECT DISTINCT *
FROM winners
WHERE tournament='$tour' AND round='$round'";
LOOP(){ //get 1 member number
$mem_nr = ['mem_nr']; //assign mem_nr to variable
STEP2: GET the count(number of times) ^ABOVE^ member number appears in table
"$sql="SELECT *, count(member_nr) as nrWins
FROM winners
where member_nr ='$memNr' and tournament='$tournament' AND round='$round'";"
LOOP(){//get count
STEP 3: DISPLAY DATA
echo $row=['nrWins'] //Display Number Wins
echo $memNr
}//END LOOP
}//END LOOP
My Problem:
The above does not seem very efficient to me, im looking for the shortest most efficient way to return the count of member numbers in table above, any ideas / suggestions are welcomed
Try something like this:
SELECT *, COUNT(*) AS `wins`
FROM `winners`
WHERE `tournament` = '$tournament'
AND `round` = '$round'
GROUP BY `member_nr`
ORDER BY `wins` DESC
select tournament,round,member_nr,count(*)
from table
where tournament = 'EPL'
and round = 12
group by tournament,round,member_nr
order by count(*) desc

Taking long time executing complex mySql query

My query looks like this:
$result_portlist=mysql_query("
SELECT
portfolio AS the_port,
SUM(balance * course) AS the_balance,
SUM(insurance * course) AS the_insurance
FROM banks_all
WHERE CONCAT(balance, insurance)!='0'
GROUP BY portfolio
",$db);
$myrow_portlist=mysql_fetch_array($result_portlist);
if(mysql_num_rows($result_portlist)>0) {
do {
echo '<span> value1, vaule2, value3...</span>';
$result_portlist1=mysql_query("
SELECT
department AS the_department,
SUM(balance * course) AS the_balance,
SUM(insurance * course) AS the_insurance
FROM banks_all
WHERE CONCAT(balance, insurance)!='0'
AND portfolio='$myrow_portlist[the_port]'
GROUP BY department
",$db);
$myrow_portlist1=mysql_fetch_array($result_portlist1);
if (mysql_num_rows($result_portlist1)>0) {
do {
echo '<span> value1, vaule2, value3...</span>'
$result_portlist2=mysql_query("
SELECT
manager_name AS the_manager,
SUM(balance * course) AS the_balance,
SUM(insurance * course) AS the_insurance
FROM banks_all
WHERE CONCAT(balance, insurance)!='0'
AND portfolio='$myrow_portlist[the_port]'
AND department='$myrow_portlist1[the_department]'
GROUP BY manager_name
",$db);
{
do {
echo '<span> value1, vaule2, value3...</span>';
} while ($myrow_portlist2=mysql_fetch_array($result_portlist2));
}
} while ($myrow_portlist1=mysql_fetch_array($result_portlist1));
}
} while ($myrow_portlist1=mysql_fetch_array($result_portlist1));
}
So this query takes hours to execute for table with 40,000+ rows with hundreds of combinations of portfolio+department+manager_name. What I thought was to make one query at start that would group values by manager_name and then let php group portfolio and department. After creating this query, my mind has just blown up and has no free memory left to think :)
Please advice me how to rearrange this query or how to simplify it to take less time to execute.
Thanks in advance.
EDIT: here is image, how my table (with nested tables) look like:
IMAGE
The reason why it takes a lot of time is because you are executing a massive amount of queries... Let's say you have 10 portfolios, in 10 departments, you'd make 100 queries. This amount is insane, and reducing the number of queries is pretty simple in your case.
I would simply grab all the data in one query, and use a 3 level group by with a rollup:
$result=mysql_query("
SELECT
portfolio AS the_port,
department AS the_department,
manager_name AS the_manager,
SUM(balance * course) AS the_balance,
SUM(insurance * course) AS the_insurance
FROM banks_all
WHERE
CONCAT(balance, insurance)!='0'
GROUP BY
portfolio,
department,
manager_name
with ROLLUP
ORDER BY the_port,the_department,the_manager;
",$db);
echo '<table>';
while($row = mysql_fetch_assoc($result)){
if($row['the_port'] === null){
//This is the big total row... Let's skip it for now shall we?
continue;
}
echo '<tr>';
if($row['the_department'] === null){
echo '<td>Portfolio: '.$row['the_port'].'</td>';
}else{
if($row['the_manager'] === null){
echo '<td>Department: '.$row['the_port'].'</td>';
}else{
echo '<td>Manager: '.$row['the_port'].'</td>';
}
}
echo '<td>'.$row['the_balance'].'</td>';
echo '<td>'.$row['the_insurance'].'</td>';
echo '</tr>';
}
echo '</table>';
This query will return all lines grouped by portfolio then grouped by department, then grouped by manager. This would return all rows from the finest point (your third while) but with ROLLUP you will also get a row for the other group by levels. This is exactly as if you would have done GROUP BY portfolio,department and GROUP BY portfolio inside the same query.
In the rolled up rows, the value of the keys omitted from the group by will be NULL. So you can easily check on the_manager, when it's null it means you have the full department, when the_department is null you have the full portfolio.

Best way to sum and seperate by date in MYSQL with/witout php

Hi i have such table information:
what i want to do with php with while or just in mysql, is to SUM (time_used) of the rows with status 44 until its reached row with status 55. after that it should begin from start with new summing.
first query should return 37, second 76 (keep in mind it should be universal, for unlimited occurrences of 55 status row)
i thought of a way with time/date filtering and have this:
select sum(time_used) as sumed
from timelog
where start_time > (select end_time from timelog where (status='55')
ORDER BY id DESC LIMIT 1) ORDER BY id DESC
but this works only for last combination of 44 and 55
i know i will need two way filtering( < end_time and > end_time) so it will work for all cases, but cant think of a way to do it in php
can anyone help me?
EDIT:
sqlfiddle whoever want it:
http://sqlfiddle.com/#!2/33820/2/0
There are two ways to do it: Plain SQL or PHP. If you treat thousands of rows, it may be interresting to choose between the two by testing performance.
Plain SQL
select project_id, task_id, user_id, sum(time_used) as time_used,
min(start_time) as start_time, max(end_time) as end_time, max(comment) as comment from
(select t.id, t.project_id, t.task_id, t.user_id, t.time_used,
count(t2.id) as count55, t.start_time, t.end_time, t.comment
from timelog t
left join timelog t2 on t.id>t2.id and t2.status=55 and t.task_id=t2.task_id
group by t.id) as t
group by count55;
I assume here that a task can belong to one user only
SQL and PHP
$link = mysqli_connect( ... );
$query = "select id, project_id, task_id, user_id, time_used, start_time, end_time, status
from timelog order by id";
$result = mysqli_query($link, $query);
$table = array();
$time_used = 0;
$start_sum = true;
$i = 0;
while($row = mysqli_fetch_assoc ($result)){
if($start_sum){
$table[$i] = $row;
$start_sum = false;
} else {
$table[$i]['time_used'] += $row['time_used'];
$table[$i]['end_time'] += $row['end_time'];
}
if($row['state'] == 55){
$i++;
$start_sum = true;
}
}
If two tasks can run in simultaneously, solution 1 will work, but solution 2 will need to be adapted in order to take this in account.
here is my intepretation:
http://sqlfiddle.com/#!2/33820/45
set #n=0;
select project_id, task_id, user_id,sum(time_used) from (
SELECT time_used,project_id, task_id, user_id,
#n:=if(status=55,#n+1,#n),
if(status=55,-1,#n) as grouper FROM timelog
) as t
where grouper>-1
group by grouper;
I'm neither a php nor MySQL programmer, but I can explain the logic you want to follow. You can then code it.
First, query your db and return the results to php.
Next, set two sum variables to 0.
Start looping through your query results. Increment the first sum variable until you reach the first row that has status 55. Once you do, start incrementing the second variable.
The tricky part will be to sort your query by the row number of the table. Here is a link that will help you with that part.

Group by mysql data that i need to expand one cell

I'm working on a job at the minute where all the products within the store need to be brought in and show how many orders have been put through in-between that time period which was easy to do, but it also in the same table needs to split the quantity of the orders of that product into the separate months that it was ordered in, is there any way to expand the data from one cell that's been group and do a count on it and then separate it into sub months?
$this->obDb->query ="SELECT vSku,fOrdertime,iOrderStatus,fPrice,SUM(iQty) as iQty,tShortDescription,fBuyprice as totalBuyPrice, vTitle FROM ".ORDERS.",".ORDERPRODUCTS." WHERE iOrderid_FK=iOrderid_PK AND ";
$this->obDb->query.=$statusquery;
if(isset($this->request['start_date']) & $this->request['start_date']>0){
$this->obDb->query.=" AND tmOrderDate >='".$this->request['start_date']."'";
}else{
$this->err=1;
$this->errMsg=INVALID_START_DATE."<br>";
}
if(isset($this->request['end_date']) & $this->request['end_date']>0){
$this->obDb->query.=" AND tmOrderDate <='".$this->request['end_date']."' GROUP BY vTitle";
}else{
$this->err=1;
$this->errMsg.=INVALID_END_DATE;
}
if($this->err==0){
$queryRs = $this->obDb->fetchQuery();
$recordCount=$this->obDb->record_count;
if($recordCount>0){
$this->ObTpl->set_var("TPL_VAR_FROMDATE", $this->libFunc->dateFormat2($this->request['start_date']));
$this->ObTpl->set_var("TPL_VAR_TODATE", $this->libFunc->dateFormat2($this->request['end_date']));
for($i=0;$i<$recordCount;$i++)
{
$this->ObTpl->set_var("TPL_VAR_STATUS","Incomplete");
if($queryRs[$i]->iOrderStatus==1){
$this->ObTpl->set_var("TPL_VAR_STATUS","Complete");
}
If I understand what you're asking you could try
SELECT datecol, COUNT(id)
FROM your_table
WHERE datecol BETWEEN date1 AND date2
GROUP BY productId, YEAR(datecol), MONTH(datecol)
ORDER BY datecol

Categories