Conditionally Count a MYSQL Column Rows and Output Data via PHP - php

Sorry i am new to this. Just trying to learn. I am trying to conditionally count the number of times a particular condition occurs in SQL, using the case and count functions. This counts the number of males/females stored in eeg table. Here is my SQL query.
SELECT COUNT(CASE WHEN `Gender` = 'Male' THEN 1 END),
COUNT(CASE WHEN `Gender` = 'Female' THEN 1 END)
FROM `eeg`
This outputs the data when i run the query on the mysql backend (phpmyadmin), but in my php file, I get an "Undefined Index" error for those 2 rows. All othjer rows are perfectly okay. I do not know how to output those particular set of data to a variable.
Here is the SQL query (in full) in the php file:
$result = mysql_query("SELECT MONTH(ScanDate), YEAR(ScanDate),
COUNT(Investigation),
COUNT(CASE WHEN `Gender` = 'Male' THEN 1 END),
COUNT(CASE WHEN `Gender` = 'Female' THEN 1 END),
SUM(InvestigationAmount), SUM(AmountDue)
FROM eeg
WHERE Investigation = '{$investigation}'
AND ScanDate BETWEEN '{$ScanDate1}'
AND '{$ScanDate2}'");
Here is the while loop (in full):
while($row=mysql_fetch_array($result)){
$month_doe=$row['MONTH(ScanDate)'];
$year_doe=$row['YEAR(ScanDate)'];
$si=$row['COUNT(Investigation)'];
$male=$row["COUNT(CASE WHEN 'Gender' = 'Male' THEN 1 END)"];
$female=$row["COUNT(CASE WHEN 'Gender' = 'Female' THEN 1 END)"];
$sum_investigation=number_format($si);
$sia=$row['SUM(InvestigationAmount)'];
$sum_investigationamount=number_format($sia);
$srd=$row['SUM(AmountDue)'];
$sum_rebatedue=number_format($srd);
}
Thank you for your help. Been literally pulling my hair out, but love to learn and improve. And yes, mysql_query is depreciated :D
screenshots below:
Code screenshot

Use an alias for the expressions and use the alias to access the results of the expressions from php:
$result = mysql_query("SELECT MONTH(ScanDate) as sdyear,
YEAR(ScanDate) as sdmonth,
COUNT(Investigation) as investigation,
COUNT(CASE WHEN `Gender` = 'Male' THEN 1 END) as MaleCount,
COUNT(CASE WHEN `Gender` = 'Female' THEN 1 END) as FemaleCount,
SUM(InvestigationAmount) as investigationamount,
SUM(AmountDue) as amountdue
FROM eeg
WHERE Investigation = '{$investigation}'
AND ScanDate BETWEEN '{$ScanDate1}'
AND '{$ScanDate2}'");
while($row=mysql_fetch_array($result)){
$month_doe=$row['sdmonth'];
$year_doe=$row['sdyear'];
$si=$row['investigation'];
$male=$row["MaleCount"];
$female=$row["FemaleCount"];
$sum_investigation=number_format($si);
$sia=$row['investigationamount'];
$sum_investigationamount=number_format($sia);
$srd=$row['amountdue)'];
$sum_rebatedue=number_format($srd);
}
I would use this approach for every field that is an expression (the other sum() fields in the above query).

Related

How to fetch data from Database table by using MySQL query

Currently, I'm stuck here in this part of my program. I want to fetch the data from the table I created which named enrollment_confirm. I want to add the total of female students and male students then the total combined of the two gender.
Here is my code so far in MySQL.
include_once('samplesf1-db.php');
$pdo = Database::connect();
$query1 = "SELECT
COUNT(CASE WHEN UPPER(Gender) = 'TOTAL MALE' THEN 1 END) Male,
COUNT(CASE WHEN UPPER(Gender) = 'TOTAL FEMALE' THEN 1 END) Female,
COUNT(CASE WHEN Gender IS NULL THEN 1 END) 'Not Assigned',COUNT(LRN) AS 'COMBINED' FROM enrollment_confirm";
$result = mysqli_query($con, $query1);
while($row = mysqli_fetch_array($result)){
echo $row['Gender'];
}
Database::disconnect();
?>
Is there anything
So, when I run the code. This is what it says.
enter image description here
Can you tell me if I did something wrong in the query?

PHP/SQL select based on sum result

I'm having a hard time limiting my query results based on sum. Example code:
$rows = Entry::find()
->section('cities')
->select('state')
->having("sum(case when covered = '1' then 1 else 0 end) = 0")
->asArray()
->all();
I want to only select states where 0 cities are "covered". Running my code above the "having" line seems to be ignored (it includes both zero and non-zero cases). I tried using "where" instead of "having" but it results in a PDOException - "Invalid use of group function". I assume "having" is the right approach, but that I'm making a novice mistake -- any tips?
/*** UPDATE 1 ***/
Thanks #scaisEdge and #angelm for the tip -- groupBy helps, but it's still not working as expected. It seems the "having" line is still ignored. With modified code:
$test = Entry::find()
->section('cities')
->select(['state', 'covered', "sum(case when covered = '1' then 1 else 0 end) as numCovered"])
->groupBy('state')
->having("sum(case when covered = '1' then 1 else 0 end) = 0")
->asArray()
->all();
I log the following results:
{state: "AL", covered: "0", numCovered: "0"}
{state: "AK", covered: "0", numCovered: "0"}
{state: "CA", covered: "1", numCovered: "19"}
{state: "CO", covered: "0", numCovered: "0"}
...
As you can see above, states (CA) are included when numCovered is clearly not 0.
I also tried the following code for "having" (which I assume is the same):
->having("numCovered = 0")
/*** UPDATE 2 ***/
Using a reduced test case suggested by #cpalmer still results in "CA" being selected despite having numCovered = 19. I'm now wondering if this is a peculiarity with Craft CMS, since it would seem my query is correct?
$test = Entry::find()
->section('cities')
->select('state')
->groupBy('state')
->having("sum(case when covered = '1' then 1 else 0 end) = 0")
->asArray()
->all();
Is there a way to write this query without having?
/*** UPDATE 3 ***/
As suggested by the DB Fiddle posted by #pocketrocket my sql should work. Dumping the raw sql suggests the having line is ignored. The issue likely resides with CraftCMS/Yii and my lack of understanding of the environment.
First of all: I am total with #Olivier, you should decouple the SQL part of your question from the architecture itself. For the SQL part, it's important to let others know which database or SQL dialect you use (MySQL, PostgreSQL, MsSQL...).
Just guessing it's MySQL what you are using:
Both ways should actually work, repeating the querypart in having or referencing it by name as suggested by user126587
If both don't work and you would like to work without having maybe you can implement a subselect?
SELECT
state,
sum(case when covered = '1' then 1 else 0 end) as numCovered
FROM cities
GROUP BY state
HAVING sum(case when covered = '1' then 1 else 0 end) = 0;
SELECT
state,
sum(case when covered = '1' then 1 else 0 end) as numCovered
FROM cities
GROUP BY state
HAVING numCovered = 0;
SELECT * FROM (
SELECT
state,
sum(case when covered = '1' then 1 else 0 end) as numCovered
FROM cities
GROUP BY state
) sub_select
WHERE sub_select.numCovered = 0;
You can play around with it here: DB Fiddle Link
try add a groupBy() for state
$rows = Entry::find()
->section('cities')
->select('state')
->groupBy('state')
->having("sum(case when covered = '1' then 1 else 0 end) = 0")
->asArray()
->all();
Try removing 'covered' from your selected columns. In some SQL databases, when you group your data, simply having a column in your select statement that isn't in the group by statement or in an aggregate can cause an error. In your case, I think this column is causing the unexpected results. If you really want to include it, throw it into an aggregate and alias it, like 'MAX(covered) as covered'
$test = Entry::find()
->section('cities')
->select(['state', "sum(case when covered = '1' then 1 else 0 end) as numCovered"])
->groupBy('state')
->having("sum(case when covered = '1' then 1 else 0 end) = 0")
->asArray()
->all();
Try putting in the having part "numCovered = 0".
Well my guess is you are forgetting a single quote around the 0 in your having clause.
$test = Entry::find()
->section('cities')
->select('state')
->groupBy('state')
->having("sum(case when covered = '1' then 1 else 0 end) = '0'")
->asArray()
->all();

SQL Server query on php

I'm begginner in this field so I need help.
I want to get integer value from this select. When I run this query in sql server - it returns correct value (so that part is okay)
My idea is to get integer value of $select -> put it in $value variable and use it after that.
Here is working sql expression:
$select = "SELECT COUNT (*) broj (SELECT a.CaseNo as CaseNo,
b.Naruc as Naruc,
b.Opis as Opis,
b.Vrijednost as cijena,
CONVERT(VARCHAR(50),b.Datumpn, 127) as datum_predaje,
(case when b.Kn IS NULL then 0 when b.Kn IS not null then b.Kn end) as kat1,
(case when b.Kn2 IS NULL then 0 when b.Kn2 IS not null then b.Kn2 end) as kat2,
(case when b.Kn3 IS NULL then 0 when b.Kn3 IS not null then b.Kn3 end) as kat3,
a.DateInserted as datum_unosa
FROM [Therefore].[dbo].[za_slanje_maila] a, [Therefore].[dbo].[TheCase1] b
WHERE CONVERT(date,a.DateInserted) = '".$today."'
AND a.DateInserted < '".$today3."'
AND a.CaseNo = b.CaseNo
AND b.Naruc is not null
AND b.Opis is not null
AND b.Vrijednost is not null
AND b.Datum_predaje is not null) broj";
After that, I tryed this
$data_api = sqlsrv_query($conn, $select, array(), array("Scrollable" => SQLSRV_CURSOR_KEYSET));
And then I try to call
$value = $data_api['broj']
- but that is empty.
How can I assign that value to the variable $value?
Thanks.
sqlsrv_query() doesn't return an array yet, but statement resource (or false on error). You can then use this resource to get the data array with sqlsrv_fetch_array() function.

MySQL Advanced multidimensional query with CONCAT, JSON and IF statement

I working on one complex listing from database and decide to do all possible requests via one query.
Here is working example:
"SELECT
`c`.`categories_id`,
`c`.`categories_status`,
IF(`c`.`categories_status` = 1, 'Active', 'Not Active') AS `categories_status_name`,
TRIM(`cd`.`categories_name`) AS `categories_name`,
TRIM(`cd`.`concert_date`) AS `concert_date`,
TRIM(`cd`.`concert_time`) AS `concert_time`,
TRIM((
SELECT
CONCAT(
'{\"total_quantity\":',
SUM(CASE WHEN `p`.`products_quantity` > 0 THEN `p`.`products_quantity` ELSE 0 END),
',\"total_price\":\"',
SUM(`p`.`products_price`),
'\"}'
)
FROM
`products_to_categories` `ptc`,
`products` `p`
WHERE
`ptc`.`section_id` = `cd`.`section_id`
AND
`p`.`products_id` = `ptc`.`products_id`
)) AS `products_available`,
TRIM((
SELECT
CONCAT(
'{\"total_quantity\":',
SUM(CASE WHEN `op`.`products_quantity` > 0 THEN `op`.`products_quantity` ELSE 0 END),
',\"total_price\":\"',
SUM(`op`.`final_price`),
'\"}'
)
FROM
`products_to_categories` `ptc`,
`orders_products` `op`
WHERE
`ptc`.`section_id` = `cd`.`section_id`
AND
`op`.`products_id` = `ptc`.`products_id`
AND
`op`.`orders_products_status` != 1
)) AS `products_sold`,
TRIM((
SELECT
CONCAT(
'{\"total_quantity\":',
SUM(CASE WHEN `op`.`products_quantity` > 0 THEN `op`.`products_quantity` ELSE 0 END),
',\"total_price\":\"',
SUM(`op`.`final_price`),
'\"}'
)
FROM
`products_to_categories` `ptc`,
`orders_products` `op`
WHERE
`ptc`.`section_id` = `cd`.`section_id`
AND
`op`.`products_id` = `ptc`.`products_id`
AND
`op`.`orders_products_status` = 1
)) AS `products_pending`
FROM
`categories` `c`,
`categories_description` `cd`
WHERE
`c`.`categories_id` = `c`.`section_id`
AND
`cd`.`categories_id` = `c`.`categories_id`
GROUP BY `c`.`categories_id`
ORDER BY `c`.`categories_status` DESC;"
This work great but my main problem is how to do check IF/ELSE or CASE WHEN for custom defined new fields: products_available, products_sold and products_pending?
Problem is that if products not exists inside table orders_products I not get my generated JSON and that's made a small conflict inside PHP.
I can do check in PHP but want to avoid that part and just print JSON like:
{"total_quantity":0,"total_price":"0.0000"}
FROM
`products_to_categories` `ptc`,
`orders_products` `op`
*
WHERE `products_id` =
(SELECT COALESCE(`products_id`,0))
*
AND
`ptc`.`section_id` = `cd`.`section_id`

problem in counting two fields in one query

guys i need to count new private messages and old one from a table
so first thing come to mind is using mysql_num_rows and easy thing to do
// check new pms
$user_id = $userinfo['user_id'];
$sql = "SELECT author_id FROM bb3privmsgs_to WHERE user_id='$user_id' AND (pm_new='1' OR pm_unread='1')";
$result = $db->sql_query($sql) ;
$new_pms = $db->sql_numrows($result);
$db->sql_freeresult($result);
// check old pms
$sql = "SELECT author_id FROM bb3privmsgs_to WHERE user_id='$user_id' AND (pm_new='0' OR pm_unread='0')";
$result = $db->sql_query($sql) ;
$old_pms = $db->sql_numrows($result);
$db->sql_freeresult($result);
but how can i count these two fields just in one statement and shorter lines ?~
Use this query instead:
SELECT SUM(CASE WHEN pm_new = '1' OR pm_unread = '1' THEN 1 ELSE 0 END) AS new_pms,
SUM(CASE WHEN pm_new = '0' OR pm_unread = '0' THEN 1 ELSE 0 END) AS old_pms
FROM bb3privmsgs_to
WHERE user_id='$user_id'
Here's a MySQL-specific version that reads more cleanly:
SELECT COUNT(IF(pm_new = '1' OR pm_unread = '1', 1, NULL)) AS new_pms,
COUNT(IF(pm_new = '0' OR pm_unread = '0', 1, NULL)) AS old_pms
FROM bb3privmsgs_to
WHERE user_id='$user_id'
MySQL will cast comparisons to 1 or 0. You can use SUM() to add up the portion of the WHERE clause you were trying to count results for.
This is a (MySQL specific) shorter alternative to the CASE WHEN examples.
SELECT
SUM(pm_new='1' OR pm_unread='1') as new_pms,
SUM(pm_new='0' OR pm_unread='0') as old_pms
FROM bb3privmsgs_to
WHERE user_id='$userid'
In SQL Server, you can do something like this:
SELECT
SUM(CASE WHEN pm_new='1' OR pm_unread='1' THEN 1 ELSE 0 END),
SUM(CASE WHEN pm_new='0' OR pm_unread='0' THEN 1 ELSE 0 END)
FROM
bb3privmsgs_to WHERE user_id='$user_id'
I'll suppose you can do about the same thing in mySql, let me get back to you on the details...
As a lazy alternative to some of the other suggestions:
SELECT SUM(newPMS) AS newPMS,
SUM(oldPMS) AS oldPMS
FROM ( SELECT COUNT(author_id) AS newPMS,
0 AS oldPMS
FROM bb3privmsgs_to
WHERE user_id='$user_id'
AND (pm_new='1' OR pm_unread='1')
UNION
SELECT 0 AS newPMS
COUNT(author_id) AS oldPMS
FROM bb3privmsgs_to
WHERE user_id='$user_id'
AND (pm_new='0' OR pm_unread='0')
)

Categories