mysql grouping a status field - mysql

I have a table
id, location, status
1, london, 1
2, london, 0
3, boston, 1
4, boston, 1
I'd like my query to generate something like this: -
location, status_1, status_0
london, 1, 1
boston, 2, 0
so far I have: -
select count(id) as freq, location from my_table
group by location order by freq desc;
I'm completely lost as to where to go from here.

That sort of transformation is better done in whatever client is issuing the query, but if you have to do it in the database, then
select location,
sum(status = 1) AS status_1,
sum(status = 0) AS status_0
from my_table
group by location
it's a bit hackish, but the 'status = 1' when status really is 1 will evaluate to a boolean true, which MySQL will politely cast to an integer '1', which then gets summed up. Same goes for when status is 0 and status = 0 evaluates to true.

So you want to count the records for each status per city?
In the query below, I group by location (like your did), and then add a sum for each state. Inside the sum is a case, that either returns 1 if the record matches the desired state, or 0 otherwise. That way, you effectively count the number of records for each state per location.
select
a.location,
sum(case when a.status = 1 then 1 else 0 end) as status_1,
sum(case when a.status = 0 then 1 else 0 end) as status_0
from
YourTable a
group by
a.location

select location,
sum(case when status = 1 then 1 else 0 end) as status_1,
sum(case when status = 0 then 1 else 0 end) as status_0,
from my_table
group by location;

Related

Count different values in a column, while doing total and group by different column values

We have a table with data from different nodes and one of the column will have status report as "compliant or non-compliant", sample data as below
I want to filter the table in such a way that if any of the checks on a node shows non compliant, it should be flagged as non-compliant and rest as compliant. Using below query i am able to do it
SELECT COUNT(*) AS total_nodes,
SUM(fully_compliant = 0) AS Non_compliant_nodes,
SUM(fully_compliant = 1) AS compliant_nodes
FROM (
SELECT Node, CASE WHEN SUM(Status = 'Compliant') = COUNT(*) THEN 1 ELSE 0 END AS fully_compliant
FROM your_table GROUP BY Node
)
Now, i want to group and split the result by dept as below, how can i achieve this
I think you're looking for this:
select dept,
count(*) as total_nodes,
sum(case when non_compliant_chk = 0 then 1 else 0 end) as compliant_nodes,
sum(case when non_compliant_chk > 0 then 1 else 0 end) as non_compliant_nodes
from (
select dept,
node,
sum(case when 'Non-Compliant' then 1 else 0 end) as non_compliant_chk
from your_table
group by dept,
node
) v
group by dept;
With few modifications to what Brian suggested, I am able to get the desired result
select dept,
count(*) as total_nodes,
sum(case when non_compliant_chk = 0 then 1 else 0 end) as compliant_nodes,
sum(case when non_compliant_chk > 0 then 1 else 0 end) as non_compliant_nodes
from (
select dept,
node,
COUNT(CASE WHEN Compliance-Status = 'Non-Compliant' THEN 1 END) 'non_compliant_chk'
from table WHERE DOR >= DATE(NOW()) - INTERVAL 7 DAY
group by Dept,
Node
) v
group by Dept;

MySQL Group By Query X or not X

This should be easy but I have not found the answer. I have a query that is running a count and I want to group this within the query into those where State = 1 and State <>1 and have the sum for each group.
SELECT count(`id_job`) as count, `state`
FROM job_table
GROUP BY `state`;
You can query a boolean expression and group by it too:
SELECT state = 1, COUNT(*)
FROM job_table
GROUP BY state = 1
SELECT count(id_job) as count,state FROM job_table
GROUP BY case when state = 1 then 1 else 0
In MySQL, you can easily put these into columns:
select sum( state = 1 ) as state_1,
sum( state <> 1 ) as state_2
from job_table;
If state can be NULL, you want to be a bit careful. The second condition is safer as:
select sum( state = 1 ) as state_1,
sum( not state <=> 1 ) as state_2
from job_table;
Try this
SELECT SUM(CASE WHEN State=1 THEN 1 END) as count1,
SUM(CASE WHEN State<>1 THEN 1 END) as count2,
State
FROM job_table
GROUP BY state

Grouping similar values into new select statement

I have a table which looks something like this...
supplier_name status count
supplier_a Unavailable 1
supplier_a Refunded 5
supplier_a Shipped 10
supplier_z Refunded 2
supplier_z Shipped 4
I know exactly what columns I want and I would like to use the values from the first table to return values structured like the following...
supplier_name unavailable refunded shipped
supplier_a 1 5 10
supplier_z 0 2 4
(note: in cases where there is no value for a specific column it should be set to 0)
Would this be possible to achieve in a query?
I think something like this should work:
SELECT Supplier_Name,
MAX(CASE WHEN STATUS = 'Unavailable' THEN Count ELSE 0 END) as Unavailable,
MAX(CASE WHEN STATUS = 'Refunded' THEN Count ELSE 0 END) as refunded,
MAX(CASE WHEN STATUS = 'Shipped' THEN Count ELSE 0 END) as shipped
FROM YourTable
GROUP BY Supplier_Name
And here is the SQL Fiddle.
Good luck.
Try this:
SELECT
supplier_name,
SUM(COALESCE(CASE WHEN status = 'unavailable' THEN `count` END, 0)) unavailable,
SUM(COALESCE(CASE WHEN status = 'refunded' THEN `count` END, 0)) refunded,
SUM(COALESCE(CASE WHEN status = 'shipped' THEN `count` END, 0)) shipped
FROM tbl
GROUP BY supplier_name
SQL FIDDLE DEMO

Grouping results by id and create new columns

I have a table which looks something like the following...
id price condition sell
21039 20.40 new 0
21039 20.41 used 1
12378 10.40 new 1
12378 5 used 0
45898 30.30 new 1
45898 12.20 used 0
(note: there will only ever be 1 new and used value for each id)
What I am trying to do is group all rows with the same id number but in the process creating new columns for each condition, which should look something like...
id new_price new_sell used_price new_sell
21039 20.40 0 20.41 1
12378 10.40 1 5 0
45898 30.30 1 12.20 0
All that I have come up with is the following query, which looks silly
SELECT id, price, condition,
IF(price > 3, 1, 0) AS sell
FROM products
GROUP BY id
How can I get the desired affect of the 2nd table.
This is known as a pivot table. It is done with a series of CASE statements for each column you need to produce, along with an aggregate MAX() or SUM() to eliminate NULLs and collapse it down to a single row.
SELECT
id,
SUM(CASE WHEN `condition` = 'new' THEN price ELSE 0 END) AS new_price,
SUM(CASE WHEN `condition` = 'new' THEN sell ELSE 0 END) AS new_sell,
SUM(CASE WHEN `condition` = 'used' THEN price ELSE 0 END) AS used_price,
SUM(CASE WHEN `condition` = 'used' THEN sell ELSE 0 END) AS used_sell
FROM
products
GROUP BY id
Without the SUM() and GROUP BY, you would still get 2 rows per id, with each having half its columns (not matched by condition in the CASE) as NULL. The SUM() (could also use MAX() in this case) eliminates the NULLs and produces one row since aggregate functions exclude NULL values while the GROUP BY groups the rows by id.
Here is a working sample on SQLFiddle.com
Update after comment:
To calculate sell based on the price, just replace the condition in the sell CASE statements:
SELECT
id,
SUM(CASE WHEN `condition` = 'new' THEN price ELSE 0 END) AS new_price,
SUM(CASE WHEN `condition` = 'new' AND price > 3 THEN 1 ELSE 0 END) AS new_sell,
SUM(CASE WHEN `condition` = 'used' THEN price ELSE 0 END) AS used_price,
SUM(CASE WHEN `condition` = 'used' AND price > 3 THEN 1 ELSE 0 END) AS used_sell
FROM
products
GROUP BY id
(Updated sample...)

MySQL - Conditional COUNT with GROUP BY

I'm trying to refine a query that I am currently using:
SELECT `puid`,
COUNT(DISTINCT `droid_v`) AS DROID,
COUNT(DISTINCT `sig_v`) AS sig,
SUM(NoExt) AS hits
FROM temp
GROUP BY `puid`
And I need to get it to only count droid_v where droid_V is greater than 0. Is it possible to condition the count in this way? At the moment, it is counting zero values as countable, and I can't really change the zeros to null values.
I do not need to know the count value for droid_V = 0, I only need to count it if it has a number greater than 0. That number will always be either 0, 1, 2, 3, or 4.
I have tried:
SELECT `puid`,
COUNT(DISTINCT CASE WHEN `droid_v` > 0 THEN 1 END) AS DROID,
COUNT(DISTINCT `sig_v`) AS sig,
SUM(`NoExt`) AS hits
FROM temp
GROUP BY `puid`
But this gives a binary result (either 0 or 1) not the count I am expecting.
example output =
puid DROID sig hits
No PUID 1 1 252
x-fmt/92 1 5 1008
anticipated output:
puid DROID sig hits
No PUID 1 1 252
x-fmt/92 3 5 1008
Sample data:
id;puid;droid_v;sig_v;speed;Ext;NoExt;tally
1;"No PUID";"3";"v13";"SLOW";"0";"63";"63"
2;"x-fmt/92";"3";"v13";"SLOW";"63";"0";"63"
3;"x-fmt/92";"3";"v37";"SLOW";"63";"63";"126"
4;"x-fmt/92";"3";"v45";"SLOW";"63";"63";"126"
5;"x-fmt/92";"3";"v49";"SLOW";"63";"63";"126"
6;"x-fmt/92";"3";"v50";"SLOW";"63";"63";"126"
7;"x-fmt/92";"5";"v13";"SLOW";"63";"0";"63"
8;"No PUID";"5";"v13";"SLOW";"0";"63";"63"
9;"x-fmt/92";"5";"v37";"SLOW";"63";"63";"126"
10;"x-fmt/92";"5";"v45";"SLOW";"63";"63";"126"
11;"x-fmt/92";"5";"v49";"SLOW";"63";"63";"126"
12;"x-fmt/92";"5";"v50";"SLOW";"63";"63";"126"
13;"No PUID";"6";"v13";"FAST";"0";"63";"63"
14;"x-fmt/92";"6";"v13";"SLOW";"63";"0";"63"
15;"No PUID";"6";"v13";"SLOW";"0";"63";"63"
16;"x-fmt/92";"6";"v13";"FAST";"63";"0";"63"
17;"x-fmt/92";"6";"v37";"SLOW";"63";"63";"126"
18;"x-fmt/92";"6";"v37";"FAST";"63";"63";"126"
19;"x-fmt/92";"6";"v45";"FAST";"63";"63";"126"
20;"x-fmt/92";"6";"v45";"SLOW";"63";"63";"126"
21;"x-fmt/92";"6";"v49";"FAST";"63";"63";"126"
22;"x-fmt/92";"6";"v49";"SLOW";"63";"63";"126"
23;"x-fmt/92";"6";"v50";"FAST";"63";"63";"126"
24;"x-fmt/92";"6";"v50";"SLOW";"63";"63";"126"
If droid_v can only be 0, 1, 2, 3, or 4, then COUNT(DISTINCT) will never return more than 5, since there are only five possible values. Is that what you want? If so, then try this:
SELECT puid, COUNT(DISTINCT CASE WHEN droid_v > 0 THEN droid_v ELSE 0 END) - 1 AS droid /* -1 for the case where droid_v is 0 */
, COUNT(DISTINCT sig_v) AS sig
, SUM(NoExt) AS hits
Update: Oops, sorry, the above is not quite right as there might not be a zero.
It should be:
SELECT puid, COUNT(DISTINCT CASE WHEN droid_v > 0 THEN droid_v END) AS droid
If, on the other hand, you want a count of all the rows where droid_v > 0, then I think you want this:
SELECT puid, SUM(CASE WHEN droid_v > 0 THEN 1 ELSE 0 END) AS droid
, COUNT(DISTINCT sig_v) AS sig
, SUM(NoExt) AS hits
Hope this helps.
Just use a sum
so if you want to group something check this out
select city, sum( case when gender = 'male' then 1 else 0 end ) as male,
sum( case when gender = 'female' then 1 else 0 end ) as female
from person
group by city
simple as this :D
SELECT
`puid`,
COUNT(DISTINCT CASE WHEN `droid_v` > 0 THEN `droid_v` END) AS DROID,
COUNT(DISTINCT `sig_v`) AS sig,
SUM(NoExt) AS hits
This is the simplest solution I can think of:
SELECT puid,
SUM(droid_v > 0) AS DROID,
COUNT(DISTINCT sig_v) AS sig,
SUM(`NoExt`) AS hits
FROM t
GROUP BY puid
However, it is not clear if you want to count the distinct or not. If you want to count the distinct values then:
SELECT puid,
COUNT(if(droid_v > 0, droid_v, null)) AS DROID,
COUNT(DISTINCT sig_v) AS sig,
SUM(`NoExt`) AS hits
FROM t
GROUP BY puid
add this to the query
WHERE droid_v > 0