matching two mysql results - php

This is a beginner php/mysql question, I've messed around for hours with various loops but I haven't been able to reach the goal. I have two tables in the db. One that contains books and one that contain the stock info for the books. Like this:
id title
1 A book
2 Another book
3 A third book
and for the stock (book_stock)
id book_id warehouse_id qty
1 1 1 12
2 1 2 45
3 2 3 22
4 3 1 78
5 1 3 15
I want to read the tables, match the id from book table with book_id from stock table and then output a summary in a html table, showing book titles and how many of each book exist in the different warehouses. What I've tried so far involves looping mysql requests, something that seems to crash since it outputs no results. I have a feeling the solutions is simple and involves arrays but my skills are lacking...
Here is my non-working code. The function works fine for 1, 2 and even 20 results entered manually, but only outputs blank table cells when looped.
//function to get stock based on book id number
function get_stock($book_row_number)
{
//get BOOK from db
$book_query="SELECT * FROM book";
$book_result=mysql_query($book_query);
//determine book info
$book_id=mysql_result($book_result,$book_row_number,"id");
$book_title=mysql_result($book_result,$book_row_number,"title");
//get LONDON stock for this book from db
$stock_query="SELECT qty FROM book_stock WHERE book_id='$book_id' AND warehouse_id='1'";
$stock_result=mysql_query($stock_query);
$stock_london=mysql_result($stock_result,0,"qty");
//get USA stock for this book from db
$stock_query="SELECT qty FROM book_stock WHERE book_id='$book_id' AND warehouse_id='2'";
$stock_result=mysql_query($stock_query);
$stock_usa=mysql_result($stock_result,0,"qty");
//get GERMANY stock for this book from db
$stock_query="SELECT qty FROM book_stock WHERE book_id='$book_id' AND warehouse_id='4'";
$stock_result=mysql_query($stock_query);
$stock_germany=mysql_result($stock_result,0,"qty");
echo "<tr><td>$book_title</td><td>$stock_london</td><td>$stock_usa</td><td>$stock_germany</td></tr>\n";
}
//find number of rows in book list
$all_query="SELECT * FROM book";
$all_result=mysql_query($all_query);
$all_rows=mysql_numrows($all_result);
// run the function on all the rows
$i=0;
while ($i < $all_rows) {
get_stock('$all_rows');
$i++;
}
EDIT: And the code as it is now
<?php
//set up connection
$user="username";
$password="paswd";
$database="database";
mysql_connect("localhost",$user,$password);
#mysql_select_db($database) or die( "Unable to select database");
//query
$book_query="SELECT
book_id,
title,
SUM(CASE WHEN warehouse_id = 1 THEN book_stock.qty ELSE 0 END) AS warehouse1,
SUM(CASE WHEN warehouse_id = 2 THEN book_stock.qty ELSE 0 END) AS warehouse2,
SUM(CASE WHEN warehouse_id = 3 THEN book_stock.qty ELSE 0 END) AS warehouse3,
SUM(CASE WHEN warehouse_id = 4 THEN book_stock.qty ELSE 0 END) AS warehouse4
FROM
book_stock
JOIN book ON book.id = book_stock.book_id
GROUP BY book_id, title";
//loop
$result = mysql_query($book_query);
if ($result) {
while ($row = mysql_fetch_assoc($row)) {
echo "<tr><td>" . htmlspecialchars($row['title']) . "</td><td>{$row['warehouse1']}</td><td>{$row['warehouse2']}</td><td>{$row['warehouse3']}</td><td>{$row['warehouse4']}</td></tr>";
}
}
else echo mysql_error();
//close database
mysql_close();
?>

You can do this in a single query, if you build it as a pivot table. The idea is that the SUM() aggregates add together the value of qty for the matching warehouse_id, or 0 when it doesn't match for each row, collapsing all the warehouses into a single row.
SELECT
SUM(CASE WHEN warehouse_id = 1 THEN qty ELSE 0 END) AS warehouse1,
SUM(CASE WHEN warehouse_id = 2 THEN qty ELSE 0 END) AS warehouse2,
SUM(CASE WHEN warehouse_id = 3 THEN qty ELSE 0 END) AS warehouse3,
SUM(CASE WHEN warehouse_id = 4 THEN qty ELSE 0 END) AS warehouse4
FROM
book_stock
WHERE book_id = $book_id
For book_id = 1, this produces a result like:
warehouse1 warehouse2 warehouse3 warehouse4
12 45 15 0
To get it for all books in rows, add a GROUP BY:
SELECT
book_id,
title,
SUM(CASE WHEN warehouse_id = 1 THEN qty ELSE 0 END) AS warehouse1,
SUM(CASE WHEN warehouse_id = 2 THEN qty ELSE 0 END) AS warehouse2,
SUM(CASE WHEN warehouse_id = 3 THEN qty ELSE 0 END) AS warehouse3,
SUM(CASE WHEN warehouse_id = 4 THEN qty ELSE 0 END) AS warehouse4
FROM
book_stock
JOIN book ON book.id = book_stock.book_id
GROUP BY book_id, title
Output from PHP is then a trivial while loop:
// Assuming you already opened your <table>
$result = mysql_query($the_big_query_above);
if ($result) {
while ($row = mysql_fetch_assoc($result)) {
echo "<tr><td>" . htmlspecialchars($row['title']) . "</td><td>{$row['warehouse1']}</td><td>{$row['warehouse2']}</td><td>{$row['warehouse3']}</td><td>{$row['warehouse4']}</td></tr>";
}
}
else echo mysql_error();
// Then don't forget to close your </table>

Related

select column names whose entries are value 1

I want to retrieve columns name from table whose value is 1
My query is give below...
mysqli_query($conn,"SELECT * FROM `tbl_therapist_schedule` WHERE `schedule_date`='30.11.2017'");
My table structure is give below...
slot1 slot2 slot3
1 1 0
2 1 1
1 1 2
3 1 0
my result...
slot1 slot2 slot3
I have the serious feeling that your data is not normalized. Instead of having separate columns for each slot, I would store all this data in a single column with metadata to relate each slot's state.
That being said, one way to get the output you want would be to aggregate over each slot column and check for the presence/absence of at least one 1 value. I then use GROUP_CONCAT to generate a CSV list of matching slots.
SELECT GROUP_CONCAT(slots)
FROM
(
SELECT
CASE WHEN SUM(CASE WHEN slot1 = 1 THEN 1 ELSE 0 END) > 0
THEN 'slot1' END AS slots
FROM tbl_therapist_schedule
WHERE schedule_date = '30.11.2017'
UNION ALL
SELECT
CASE WHEN SUM(CASE WHEN slot2 = 1 THEN 1 ELSE 0 END) > 0
THEN 'slot2' END
FROM tbl_therapist_schedule
WHERE schedule_date = '30.11.2017'
UNION ALL
SELECT
CASE WHEN SUM(CASE WHEN slot3 = 1 THEN 1 ELSE 0 END) > 0
THEN 'slot3' END
FROM tbl_therapist_schedule
WHERE schedule_date = '30.11.2017'
) t;
Demo

sql Calculate boys and girls present and absent

Can't manage to come up with a correct query to compute the total no of students
I have three tables:
student - contains student profile either male or female
2.student_attendance - contains attendance details for whether a student was present a either "0" or "1"
attendance - contains all session details where by a one session can be attended by a number of students.
I need to calculate the number of boys/girls in present or absent for a session.
my major headache is to interpreate these logic to sql
if(in_attendace =1) then
sum the number of boys as boys_present
sum the number of girls as girls_present
else
sum the number of boys as boys_absent
sum the number of girls as girls_absent
# MY closest sql is its not working :(
select
case when a.in_attendance = 1 then
SUM(CASE b.gender when 1 then 1 else 0 end ) as male_present,
SUM(CASE b.gender when 2 then 1 else 0 end ) as female_present,
ELSE
SUM(CASE b.gender when 1 then 1 else 0 end ) as male_absent,
SUM(CASE b.gender when 2 then 1 else 0 end ) as female_absent
END
from attendance_student as a inner join student as b on a.student_id = b.id where a.session_details_id = 38
Well, you are not very far from the solution, you just need to separate them into different columns(I assume that's what you want) :
select COUNT(CASE WHEN a.in_attendance = 1 and b.gender = 1 then 1 END) as male_present,
COUNT(CASE WHEN a.in_attendance = 1 and b.gender = 2 then 1 END) as female_present,
COUNT(CASE WHEN a.in_attendance = 0 and b.gender = 1 then 1 END) as male_absent,
COUNT(CASE WHEN a.in_attendance = 0 and b.gender = 2 then 1 END) as female_absent
FROM attendance_student a
INNER JOIN student b
ON a.student_id = b.id
WHERE a.session_details_id = 38

MySQL Count Records Based On Criteria Within A Group

I have a table containing the following data columns:
ord_number check
OR123 0
OR125 1
OR123 2
OR123 0
OR124 0
OR124 0
OR125 0
OR123 0
The check column indicates if we have fully supplied the order line with a value of zero or below meaning 'yes we have supplied complete' and a value of 1 or above meaning 'no we have not supplied complete' .
To calculate an order fill rate (how many orders have been filled complete) I need to know how many of the orders have only zero check results for each entry and how many have at least one positive check result.
My logic is that I need to GROUP the items and then carry out a COUNTIF within the group (this may be the wrong SQL methodology but logically it makes sense to me in terms of the outcome I'm looking for). From this query I need to return those two values into my PHP script.
The results from this data set would be:
Complete = 1 (orders with only zero checks)
Incomplete = 2 (orders where one or more lines have positive checks)
I've spent the morning trying to find a solution but can't find anything that I either understand enough or is similar enough that I can break it down and understand it.
If someone can help me by pointing me in the right direction or can provide a sample with an explanation I would be very grateful.
For 1 row with 2 counter fields use:
SELECT
SUM(CASE WHEN `check` = 1 THEN 1 ELSE 0 END) AS incomplete,
SUM(CASE WHEN `check` = 0 THEN 1 ELSE 0 END) AS complete
FROM orders
For 2 rows with 1 name use:
SELECT COUNT(`ord_number`) AS fulfillment
FROM orders WHERE (`check`=0)
UNION SELECT COUNT(ord_number)
FROM orders WHERE (`check`=1)
in which case you need to put row 1 into $complete (check=0)
and row 2 into $incomplete (check=1)
you may add:
UNION SELECT COUNT(ord_number) FROM orders
which will give you the total records on row 3.
output will be:
SELECT * FROM orders
ord_number check
---------------------
OR123 0
OR124 1
OR125 0
OR126 0
OR127 0
OR123 0
OR125 1
SELECT COUNT(`ord_number`) AS counts FROM orders or1 WHERE (`check`=0)
UNION SELECT COUNT(ord_number) FROM orders or2 WHERE (`check`=1)
UNION SELECT COUNT(ord_number) FROM orders
counts
-------
5
2
7
SELECT
SUM(CASE WHEN `check` = 1 THEN 1 ELSE 0 END) AS incomplete,
SUM(CASE WHEN `check` = 0 THEN 1 ELSE 0 END) AS complete FROM orders
incomplete complete
-------------------------
2 5
As for PHP:
for 1 row:
mysql_select_db($database_test, $test);
$query_countIn1Row = " SELECT SUM(CASE WHEN `check` = 1 THEN 1 ELSE 0 END) AS
incomplete,
SUM(CASE WHEN `check` = 0 THEN 1 ELSE 0 END) AS complete
FROM orders";
$countIn1Row = mysql_query($query_countIn1Row, $test) or die(mysql_error());
do {
$varIncomplete = $row_countIn1Row['incomplete'];
$varComplete = $row_countIn1Row['complete'];
} while ($row_countIn1Row = mysql_fetch_assoc($countIn1Row));
and for 1 column with counts:
mysql_select_db($database_test, $test);
$query_countOrders = "SELECT COUNT(`ord_number`) AS counts
FROM orders or1 WHERE (`check`=0)
UNION SELECT COUNT(ord_number) FROM orders or2 WHERE (`check`=1)
UNION SELECT COUNT(ord_number) FROM orders";
$countOrders = mysql_query($query_countOrders, $test) or die(mysql_error());
$myCounts = array();
do {
$myCounts[]= $row_countOrders['counts'];
} while ($row_countOrders = mysql_fetch_assoc($countOrders));
$complete = $myCounts[0];
$incomplete = $myCounts[1];
$total = $myCounts[2];
SELECT ord_number,IF(MAX( check) <=0 ,'COMPLETED','PENDING')
from TABLENAME
group by (ord_number )
Through this oneline query you will easily get which order is in pending status and which one is complete status
AS per your given details
The check column indicates if we have fully supplied the order line
with a value of zero or below meaning 'yes we have supplied complete'
and a value of 1 or above meaning 'no we have not supplied complete' .
it means check column can contain negative value as well as 0 for indicating the complete status and 1 or any postive integer number to indicate the pending status.
so the logic should be find the max(check) so if the max for a order is found 0 or any negative number then we will sure that order is complete and if it found a positive number it means there was a pending entry.
You can do this in two steps:
SELECT ord_number,
SUM(CASE WHEN `check` = 0 THEN 1 ELSE 0 END) as Comp,
COUNT(`check`) as total
FROM tab1
GROUP BY ord_number
This would give you the number of rows with 0 (complete) and the total number of rows for each ord_number.
Then you do a COUNT to validate when those two are equal:
SELECT CASE WHEN comp = total THEN 'COMPLETE' ELSE 'INCOMPLETE' END AS status,
COUNT(*) AS statusCount
FROM(
SELECT ord_number,
SUM(CASE WHEN `check` = 0 THEN 1 ELSE 0 END) as Comp,
COUNT(`check`) as total
FROM tab1
GROUP BY ord_number) a
GROUP BY 1;
This should get you what you want.
sqlfiddle demo
Note that i used ` around check since this is a mysql reserved word

SQL obtain first the id selected on a while, then the others from a table?

I need to put first selected item in a list, and then the rest in order by id.
My table:
id:1 car: fiat
id:2 car:ford
id:3 car:vw
id:4 car:toyota
the problem in .com/index.php?car=fiat
$car = $_GET['car'];
$results = mysqli_query($connecDB,"select * from products order by (case id when 999 then 0 else 1 end), car asc");
and the body
while($row = mysqli_fetch_array($results )){
echo '
<div id="'.$row["car"].'"></div>
';
}
In example:
if I get the value 3:
ID
3
1
2
4
5
if I get the value 4:
ID
4
1
2
3
5
I dont know where to put the variable $car to work properly.
Thanks and i apoligize for my english.
If the ID is numeric and will always be >0, this will work (I've kept the parentheses from your original query; note they're optional):
select *
from products
order by (case id when 3 then 0 else id end), car asc
If the ID can have negative values then something like this would be safer:
select *
from products
order by (case id when 3 then 0 else 1 end), id, car asc

SQL Multiple Result question

Can I use a single SQL statement to return three separate results I can display through PHP? I'm looking to formulate three different "total" counts on a single table with three different conditions.
Eg something like....
$resultGetTotals = SELECT COUNT(Total1) FROM table_xyz WHERE Status = X AS Total1
SELECT COUNT(Total2) FROM table_xyz WHERE Status = X AND Person = Y AS Total2
SELECT COUNT(Total3) FROM table_xyz WHERE Status = Y AND Person = X AS Total3
while ($rGetTotals = mysql_fetch_array($resultGetTotals)){
$Total1 = $rGetTotals["Total1"]
$Total2 = $rGetTotals["Total2"]
$Total2 = $rGetTotals["Total2"];
}
Total One is: <?php print $Total1; ?><br>
Total Two is: <?php print $Total2; ?><br>
Total Three is: <?php print $Total3; ?><br>
Any help greatly appreciated :)
SQL:
SELECT SUM(CASE WHEN t.status = X THEN 1 ELSE 0 END) AS total1,
SUM(CASE WHEN t.status = X AND t.person = Y THEN 1 ELSE 0 END) AS total2,
SUM(CASE WHEN t.status = Y AND t.person = X THEN 1 ELSE 0 END) AS total3
FROM TABLE_XYZ t
PHPified:
$result = mysql_query("SELECT SUM(CASE WHEN t.status = X THEN 1 ELSE 0 END) AS total1,
SUM(CASE WHEN t.status = X AND t.person = Y THEN 1 ELSE 0 END) AS total2,
SUM(CASE WHEN t.status = Y AND t.person = X THEN 1 ELSE 0 END) AS total3
FROM TABLE_XYZ t");
while ($row = mysql_fetch_array($result)) {
echo "Total One is: $row['total1']<br>"
echo "Total Two is: $row['total2']<br>"
echo "Total Three is: $row['total3']<br>"
}
mysql_free_result($result);
Assuming you want the number of rows for each user (and not the number of non-null values in three different columns), and then for all users, and further assuming that there are only Person X and Y in the table, use:
SELECT Person, COUNT(*) FROM table_xyz GROUP BY Person
Retrieve the two totals (for person X and person Y) and add them together to get the grand total.

Categories