MySQL Count Records Based On Criteria Within A Group - php

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

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

MySQL - Update Column if all rows are equal

I have N Rows with same SlNo but different RowNo as shown below
for eg:
SlNo RowNo Status
1 1 Opened
1 2 Closed
1 3 Opened
1 4 Closed
1 5 Opened
If all the Status Column Rows are Closed , I want to return 1.
else o.
Thanks in advance.
You can do it following:
SELECT STATUS FROM `table_1` where SLNO = 1 group by status
If you get only one record with value "Closed" then execute the next query
UPDATE `table_2` SET Ref_Status = 'Closed' WHERE SLNO = 1;
Update my_table set Status='Closed' where SlNo = 1
Find the count of all rows and check it with the count of Closed values.
Query
select t.`SlNo`,
case when t.`RowNo_Count` = t.`closed_count` then 1 else 0 end as `new_col`
from(
select `SlNo`,
count(`RowNo`) as `RowNo_Count`,
sum(case `Status` when 'Closed' then 1 else 0 end) as `closed_count`
from `your_table_name`
group by `SlNo`
)t;

How to edit this mySQL so as to combine the rows of the same id into 1 instead of 3?

The following mySQL query gets data from 2 tables, alerts_data and alerts_list. The first table has the data of an alert, and the second has the description of the alert. So in the alerts_data there are multiple rows with the same alerts_data_id that is the same with the alerts_id of alerts_list.
What i want to achieve, is to display something like this
alert number 51, 5 clicked , 2 closed
alert number 57, 13 clicked, 3 closed, 8 waiting
using mySQL or PHP (i do not know if i can get this through plain mySQL)
So for now with my knowledge I can not display the data of alert 51 in one row, but because of the different alerts_data_status i have to show 3 rows for each.
How can I do it as above?
SELECT COUNT( alerts_data_id ) AS total, alerts_data_id, alerts_data_status, alerts_list.alerts_title
FROM alerts_data
JOIN alerts_list ON
alerts_data.alerts_data_id = alerts_list.alerts_id
GROUP BY alerts_data_id, alerts_data_status
//output
total - alerts_data_id - alerts_data_status - alerts_title
5 - 51 - clicked - alert number 51
2 - 52 - closed - alert number 51
13 - 57 - clicked - alert number 57
3 - 57 - waiting - alert number 57
8 - 57 waiting - alert number 57
Note: the alerts number are just examples, it can be any number
// alert_data
id - alerts_data_id - alerts_data_status
// alerts_list
alerts_id - alerts_name - alerts_text
Here's a sqlfiddle: http://sqlfiddle.com/#!9/c70c2/1
This may be an application for GROUP_CONCAT().
You first want a summary of your alerts by alerts_data_id and alerts_data_status. This is a little complex, because your sqlfiddle has a whole bunch of empty alerts_data_status strings. Here, I'm replacing those empty strings with `?'. (http://sqlfiddle.com/#!9/c70c2/23/0)
SELECT COUNT(*) AS alerts_count,
alerts_data_id,
CASE WHEN LENGTH(alerts_data_status) = 0 THEN '?'
ELSE alerts_data_status END AS alerts_data_status
FROM alerts_data
GROUP BY alerts_data_id, alerts_data_status
You then want to roll that up inside another query
SELECT SUM(a.alerts_count) total,
a.alerts_data_id, b. alerts_name,
GROUP_CONCAT( CONCAT(a.alerts_count, ': ', a.alerts_data_status)
ORDER BY a.alerts_data_status
SEPARATOR "; " ) detail
FROM (
SELECT COUNT(*) AS alerts_count,
alerts_data_id,
CASE WHEN LENGTH(alerts_data_status) = 0 THEN '?'
ELSE alerts_data_status END AS alerts_data_status
FROM alerts_data
GROUP BY alerts_data_id, alerts_data_status
) a
JOIN alerts_list b ON a.alerts_data_id = b.alerts_id
GROUP BY a.alerts_data_id, b.alerts_name
This will give you one row for each distinct alerts_data_id. Each alert is identified by its count, its id, and its name. (http://sqlfiddle.com/#!9/c70c2/26/0)
Then the row will contain a semicolon-separated list of the counts of the different alert status.
If i understand you well i think here is what you need;
SELECT
COUNT( alerts_data.id ) AS total,
ad.id,
(SELECT count(*) from alert_list al where al.alerts_id=ad.id and alerts_data_status='clicked') as clicked,
(SELECT count(*) from alert_list al where al.alerts_id=ad.id and alerts_data_status='closed') as closed,
(SELECT count(*) from alert_list al where al.alerts_id=ad.id and alerts_data_status='waiting') as waiting,
FROM alerts_data ad
GROUP BY ad.id
Was checking other answers and your SQLFIDDLE and thought this might be a nicer approach:
SELECT alerts_list.alerts_title,
SUM(CASE WHEN alerts_data_status = 'clicked' THEN 1 ELSE 0 END) AS clicked,
SUM(CASE WHEN alerts_data_status = 'closed' THEN 1 ELSE 0 END) AS closed,
SUM(CASE WHEN alerts_data_status = 'waiting' THEN 1 ELSE 0 END) AS waiting
FROM alerts_data
JOIN alerts_list ON alerts_data.alerts_data_id = alerts_list.alerts_id
GROUP BY alerts_list.alerts_title

Getting seperate values from table with one binary field

I have table for student attendance like below:
id | Present | date
1 | 1
1 | 0
1 | 1
1 | 1
1 | 0
Now I want to get the total days he is present via single query. Is it possible?
Below is the way I used to get the student present/absent count:
select count(*) from table where present =1
select count(*) from table where present =0
But I think can I get both from one query instead of two.
select sum(present = 1) as present1,
sum(present = 0) as present0
from table
You can use the following query:
select (select count(*) from table where present=1) as "present"
, (select count(*) from table where present=0) as "absent";
Try this its working fine :
SELECT SUM( present =1 ) AS present, SUM( present =0 ) AS absent
FROM details
WHERE id =1
Screenshot :
Try this :
For all student with group by
select id,present,absent from
(
select id,sum(case when present = 1 then 1 else 0 end) as present,
sum(case when present = 0 then 1 else 0 end) as absent
from table_name
group by id
) as absen
if you want to show only one student, just add where clause in the end like this :
select id,present,absent from
(
select id,sum(case when present = 1 then 1 else 0 end) as present,
sum(case when present = 0 then 1 else 0 end) as absent
from table_name
group by id
) as absen
where id = '1'
Hope this help you..

mysql | Group and count rows

I have a table and would like to calculate values. My table:
Table votes
vote type
1 1
-1 1
1 0
-1 0
1 0
-1 1
1 0
Vote: -1 - Down; +1 - Up;
I would like to get something like this:
Count votes up type 1: 1
Count votes down type 1: 2
Votes up type 0: 3
Votes down type 0: 1
Sum votes type 1: 1+(-1)+(-1) = -1
Sum votes type 0: 1+(-1)+1+1 = 2
Is it possible to get results from mysql using single query?
Thanks!
I guess your problem is how to distinct up and down votes here.
You want to group by type (which sounds like a vote/poll ID) and then just pick up and down votes. It can be done using CASE or IF in combination with COUNT or SUM.
COUNT does not count NULL values so I suggest to wrap two COUNTs in IFs.
SELECT
type,
COUNT(IF(vote = -1, TRUE, NULL)) AS down,
COUNT(IF(vote = 1, TRUE, NULL)) AS up
FROM votes
GROUP BY type
SQL Fiddle: http://sqlfiddle.com/#!2/36008/1/0
you can write
select count(*) from table where type = 1 and vote = -1
select count(*) from table where type = 1 and vote = 1
the above will give you the result count which you want .
This will work
select sum(vote),type from table group by type;

Categories