For loop inside SQL query - php

I have a table named watersourcetype consisting of water types.
link : watersourcetype TABLE
and another table health_and_sanitation consisting of household no. and watersource_id
I have this query :
SELECT h.purok_number,
SUM(CASE WHEN hs.watersystem = 'Community water system-own' THEN 1 ELSE 0 END) AS a,
SUM(CASE WHEN hs.watersystem = 'Community water system-shared' THEN 1 ELSE 0 END) AS b,
SUM(CASE WHEN hs.watersystem = 'Deep well-own' THEN 1 ELSE 0 END) AS c,
SUM(CASE WHEN hs.watersystem = 'Deep well-shared' THEN 1 ELSE 0 END) AS d,
SUM(CASE WHEN hs.watersystem = 'Artesian well-own' THEN 1 ELSE 0 END) AS e,
SUM(CASE WHEN hs.watersystem = 'Artesian well-shared' THEN 1 ELSE 0 END) AS f,
SUM(CASE WHEN hs.watersystem = 'Dug/shallow well-own' THEN 1 ELSE 0 END) AS g,
SUM(CASE WHEN hs.watersystem = 'Dug/shallow well-shared' THEN 1 ELSE 0 END) AS h,
SUM(CASE WHEN hs.watersystem = 'River, stream, lake, spring, bodies of water' THEN 1 ELSE 0 END) AS i,
SUM(CASE WHEN hs.watersystem = 'Bottled water' THEN 1 ELSE 0 END) AS j,
SUM(CASE WHEN hs.watersystem = 'Tanker truck/Peddler' THEN 1 ELSE 0 END) AS k
FROM health_and_sanitation AS hs, house_hold AS h, f_member as f
WHERE
h.brgy_name='$brgy_name' AND
h.hh_number=hs.hh_number AND
h.hh_number=f.hh_number AND
f.is_household='HOUSEHOLD' AND
EXTRACT(YEAR FROM f.reg_date) BETWEEN '$sel_year' AND '$sel_year'
group by h.purok_number
order by h.purok_number
what i want is to put a for loop inside above sql query since table watersourcetype is dynamic another data will be added to watersourcetype soon so i dont have to define in my case statement on above query the watersystem . The query should look like this :
$qry = pg_query("select cwatertype from tbl_watersourcetype");
SQL:
SELECT h.purok_number,
// is this possible ? putting a while loop or forloop inside a query in PHP ?
while($row = pg_fetch_array($qry))
{
SUM(CASE WHEN hs.watersystem = '$row['cwatertype']' THEN 1 ELSE 0 END) AS a
}
FROM health_and_sanitation AS hs, house_hold AS h, f_member as f
WHERE
h.brgy_name='$brgy_name' AND
h.hh_number=hs.hh_number AND
h.hh_number=f.hh_number AND
f.is_household='HOUSEHOLD' AND
EXTRACT(YEAR FROM f.reg_date) BETWEEN '$sel_year' AND '$sel_year'
group by h.purok_number
order by h.purok_number
is that possible ?

If I understand your query correctly, you are trying to retrieve the number of watersourcetypes per household, with a single record returned per household. If that is indeed the case you need to use the crosstab() function from the tablefunc extension.
However, if you can get by with multiple rows giving the number of sources per watersourcetype per household then you can simply and more efficiently use the COUNT() aggregate in the SELECT statement (with some decent formatting for legibility):
SELECT h.purok_number, hs.watersystem, COUNT(hs.watersystem) AS num
FROM health_and_sanitation AS hs,
house_hold AS h,
f_member AS f
WHERE h.brgy_name='$brgy_name'
AND h.hh_number=hs.hh_number
AND h.hh_number=f.hh_number
AND f.is_household='HOUSEHOLD'
AND EXTRACT(YEAR FROM f.reg_date) BETWEEN '$sel_year' AND '$sel_year'
GROUP BY h.purok_number, hs.watersystem
ORDER BY h.purok_number;
Additionally, I am assuming that your health_and_sanitation table is a view on the watersourcetype table; otherwise you are duplicating data in two tables which is (generally) a big boo-boo. Given also your issue with additional water source type, you may want to see if your database design is in 3NF.
Cheers,
Patrick

this is an example on how to put for loop inside SELECT statement :
$qry_6_12 .= " SELECT count(ncropfarmingreasonid) as counted , " ;
for($i=2;$i<=$count_row;$i++) // loop the number of rows and used $i as ncropfarmingreasonid
{
if(($count_row-$i)==0)
{
$qry_6_12 .= "SUM(CASE WHEN ncropfarmingreasonid = ".$i." THEN 1
ELSE 0 END) a".$i."";
}
else
{
$qry_6_12 .= "SUM(CASE WHEN ncropfarmingreasonid = ".$i." THEN 1
ELSE 0 END) a".$i.",";
}
}
$qry_6_12 .= " FROM tbl_climatechange as c, tbl_household as h, tbl_barangay as b where h.chholdnumber=c.chholdnumber and b.cbrgycode=h.cbrgycode and b.cbrgyname = 'AMPAYON' ";
$query_6_12 = pg_query($qry_6_12);

Related

how to pass IF condition in sum case when

#my code
select('a.client_location_id as location_id','b.name as location_name','c.name as client_name',
DB::raw('SUM(CASE WHEN a.type = 1 employee_qty THEN 1 ELSE 0 END) as e_qty_in'),
DB::raw('SUM(CASE WHEN a.type = 2 employee_qty THEN 1 ELSE 0 END) as e_qty_out')
)
i want to do IF conditioning like , if type = 1 result is SUM employee_qty AS e_qty_in and if type 2 the result is SUM employee_qty AS e_qty_out,
#table

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

Counts on single column for different conditions

I require 3 different counts on single column for different conditions.
Table structure:
interview-
id-int(10)
c_id-int(10)
experience-varchar2(100)
experience have 3 different values-
1)positive
2)negative
3)neutral
I require 3 different counts of "count_positive", "count_negative" and "count_neutral" for where condition of c_id=10.
I know it can get by 3 different queries. Can I able to get 3 counts by single query?
SELECT
SUM(CASE experience
WHEN 'positive' THEN 1
ELSE 0
END) AS CountPositive
, SUM(CASE experience
WHEN 'negative' THEN 1
ELSE 0
END) AS CountNegative
, SUM(CASE experience
WHEN 'neutral' THEN 1
ELSE 0
END) AS CountNeutral
FROM Interview
WHERE c_id = 10
select 'Positive Count' , count(*)
from interview
where experience = 'positive'
UNION
select 'Negative Count' , count(*)
from interview
where experience = 'negative'
UNION
select 'Neutral' , count(*)
from interview
where experience = 'neutral'
This is the modified version of Adam Wenger answer:
SELECT
COUNT(CASE experience
WHEN 'positive' THEN 1
ELSE NULL
END) AS CountPositive
, COUNT(CASE experience
WHEN 'negative' THEN 1
ELSE NULL
END) AS CountNegative
, COUNT(CASE experience
WHEN 'neutral' THEN 1
ELSE NULL
END) AS CountNeutral
FROM Interview
WHERE c_id = 10
I think this works fine:
select 'count of ' + experience,
count(experience)
from interview
where c_id=10
group by experience
I got solution for active record query in Codeigniter:
$this->db->select('SUM(CASE experience
WHEN "positive" THEN 1
ELSE 0
END) AS CountPositive
, SUM(CASE experience
WHEN "negative" THEN 1
ELSE 0
END) AS CountNegative
, SUM(CASE experience
WHEN "neutral" THEN 1
ELSE 0
END) AS CountNeutral');
$this->db->where('c_id',10);
$query=$this->db->get('interview');
$result=$query->result();
$interview_experience=$result[0];
$positive_count=$interview_experience->CountPositive;
$negative_count=$interview_experience->CountNegative;
$neutral_count=$interview_experience->CountNeutral;

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