I need help with writing a query (mySQL) to
Total number of users in a project, and
Number of users in that project that have been "disabled"
Now, I can do it separately, like this:
SELECT count(users) FROM t1 WHERE project = 3
SELECT count(users) FROM t1 WHERE project = 3 AND status = "disabled"
But there's gotta be a simple way of combining the two in one query...
You can use UNION:
mysql> SELECT count(users) AS result FROM t1 WHERE project = 3 UNION
SELECT count(users) AS result FROM t1 WHERE project = 3 AND status = "disabled"
+--------+
| result |
+--------+
| 2 |
| 1 |
+--------+
Other solution are subqueries:
mysql> SELECT (SELECT COUNT(ID) FROM t1 WHERE project = 3) AS total_users,
(SELECT COUNT(ID) FROM t1 WHERE project = 3 AND status = 'disabled') AS disabled_users;
+-------------+----------------+
| total_users | disabled_users |
+-------------+----------------+
| 2 | 0 |
+-------------+----------------+
Anyway, the truth about those solutions is that two separate queries will do just fine. Only on very large systems this would matter. When we look at database performance, those two will be slower than two separate queries. The only reason we would want to do that is overhead from connection to the database.
Select
Project,
Count(Users),
Sum(Case When Status = 'Disabled' Then 1 Else 0 End)
From
T1
Group By Project
While I was typing stu gave an answer already. I had basically the same one with slightly different syntax:
select count(users), sum(if(status='disabled',1,0))
from t1
where project = 3 ;
Well you could do something like
SELECT status, count(users) FROM t1 **group by status** WHERE project = 3
to get a resultset of status and count of how many records in that status. Add all counts together for the total, remember the count for "disabled" for the disabled count.
SELECT status, count(users) FROM t1 group by status WHERE project = 3 AND status = "disabled"
Related
Consider:
SELECT(count(c.id),
case when(count(c.id) = 0)
then 'loser'
when(count(c.id) BETWEEN 1 AND 4)
then 'almostaloser'
when(count(c.id) >= 5)
then 'notaloser'
end as status,
...
When all is said and done, the query as a whole produces a set of results that look similar to this:
Count | status
--------|-------------
2 | almostaloser //total count is between 2 and 4
--------|-------------
0 | loser // loser because total count = 0
--------|-------------
3 | almostaloser //again, total count between 2 and 4
--------|-------------
What I would like to achieve:
a method to reatain the information from the above table, but add a third column that will give a total count of each status, something like
select count(c.id)
case when(count(c.id) = 0 )
then loser as status AND count how many of the total count does this apply to
results would look similar to:
Count | status |total_of each status |
--------|-------------|---------------------|
2 | almostaloser| 2 |
--------|-------------|---------------------|
0 | loser | 1 |
--------|-------------|---------------------|
3 | almostaloser| 2 |
--------|-------------|----------------------
I've been told this could be achieved using a derived table, but i've not yet been able to get them both, only one or the other.
This can be achieved with this query (you must place your original query as subquery in two places):
SELECT t1.*, t2.total_of_each_status
FROM (
-- put here your query --
) t1
INNER JOIN (
SELECT status, count(*) AS total_of_each_status
FROM (
-- put here your query --
) t2
GROUP BY status
) t2 ON t2.status = t1.status
I want to show a output table that counts all the users found in a table.
Basically I want the output to look like:
+-----------+-----------+
| user1 | user2 |
+-----------+-----------+
| 5 | 2 |
+-----------+-----------+
I'm just using a dummy table to test this. My query looks like this:
(
select
name as user1
from
users
where
name = 'root'
) UNION (
select
name as user2
from
users
where
name = 'not_root'
)
Which only outputs something like this:
+-----------+
| user1 |
+-----------+
| 5 |
| 2 |
+-----------+
EDITED
The main idea of the approach it's treat a table as two different virtual tables in subquery. We can make nested select statement e.g. (select count(*) as c from users where name = 'root') u1 MySql treats it as particular table named u1 with one row and one column named c.
select u1.c as root_cnt, u2.c as not_root_cnt
from (select count(*) as c from users where name = 'root') u1,
(select count(*) as c from users where name = 'not_root') u2
or
Moreover if you have select statement that returns only one row you can put nested selects directly in fields list
select (select count(*) as c from users where name = 'root') as root_cnt, (select count(*) as c from users where name = 'not_root') as not_root_cnt
Definite disadvantage of such approach it's extra subqueries. Method based on using case when construction free from such disadvantage.
Try this
SELECT
SUM(CASE WHEN Name = 'root' THEN 1 ELSE 0 END) user1,
SUM(CASE WHEN Name = 'not_root' THEN 1 ELSE 0 END) user2
FROM Users
You can use a case statement inside of count to get the counts in separate columns
select
count(case when name = 'root' then 1 end) user1,
count(case when name = 'not_root' then 1 end) user2
from users
where name in ('root','not_root')
It seems your query is wrong..
union won't combine the results of two queries in the way you have described above.
union would combine the result of two or more select statements but wouldn't "join" it.
You might want to use joins for this cause. still you wouldn't be able to put 5|2 in same row as it basically suggests --> fetch user 1 and user 2 values for one particular type
i think group by is a much better approach:
select user, count(user) from users group by user
I have three tables as following:
USERS TABLE
id_user| name |
---------------
1 | ...
2 | ...
SERVICES TABLE
id_service | name |
-------------------
1 | ...
2 | ...
3 | ...
USER_SERVICES TABLE (n-m)
id_user | id_service
--------------------
1 | 1
1 | 2
2 | 1
And I need to do a SELECT starting from "SELECT * FROM users" and then, getting the users by services. Ex. I need to get every user with services = 1 and services = 2 (and maybe he has other more services, but 1 and 2 for sure).
I did the following:
SELECT *
FROM `users`
INNER JOIN user_services ON users.id_user = user_services.id_user
WHERE id_service=1 AND id_service=2
But this, of course dont works since there is not a single record matching service = 1 and service = 2.
What can I do?
Add an extra join for the other service you want to check:-
SELECT *
FROM `users`
INNER JOIN user_services us1 ON users.id_user = us1.id_user AND us1.id_service=1
INNER JOIN user_services us2 ON users.id_user = us2.id_user AND us2.id_service=2
select t.*,
(select count(*) from user_services where id_user = t.id_user) how_much
from users t;
Is this what you want???
It shows the data of the users and how much services are in the services table. Other possibility is this:
select t.*,
(case when (select count(*)
from user_services where id_user = 1) > 0
then 'service1'
else 'null'
end) has_service_1
from users t;
The problem with this select is that you have to repeat this case...end as much times as id_services you have, so it doesn't make sense if the number of services is increasing over time. On the contrary, if it is a somewhat fixed number, and it is not a big number, this could be a solution.
ok this is very simple yet have been searching for 3 hours and still cant get it to work!
the scenario is i have a db with individual costs of 2 business' and i want to sum the cost of each business and present on screen. now i know this is simple enough and easily done with two SELECTS. but i want to do this in one query!
DB
|cost|business|
|100 | 1 |
|200 | 2 |
|200 | 1 |
|300 | 2 |
so from the table above we know that b1 = 300 and b2 = 500! but none of my queries work!
i have tried UNION and CASE but am unfamiliar with them.
my queries:
first try:
$buscost = mysql_query("SELECT FORMAT(sum(`cost`),2) as `b1` FROM `outgoing` WHERE `business`=1
UNION
SELECT FORMAT(sum(`cost`),2) as `b2` FROM `outgoing` WHERE `business`=2")
or die(mysql_error());
$buscost = mysql_fetch_array($busowe);
second try:
$buscost = mysql_query("SELECT
CASE WHEN `business` = 1 THEN FORMAT(sum(`cost`),2) END AS `b1` ,
CASE WHEN `business` = 2 THEN FORMAT(sum(`cost`),2) END AS `b2`
FROM `outgoing` WHERE `active`='yes' ");
$buscost = mysql_fetch_array($buscost);
*cost is set as float(11,2).
im sure im close i just dont know enough to figure it out, have found similar questions on here but none of the answers helped!
oh and if i print_r, the first only fetches the sum of b1, b2 doesnt exist! and
the second array all i get is the result set of the first case and case 2 "b2" is empty,but exists!! i have checked the tables and there is test data in there for both business'.
please help any advice or a solution is greatly appreciated.
edit:forgot to mention all results will also need to be filtered with where active='yes'
Youn need to group by:
SELECT business, FORMAT(sum(`cost`),2) AS cost
FROM outgoing
WHERE active = 'yes'
GROUP BY business
if you want the format:
business | cost
b1 | 300
b2 | 500
or
SELECT
(
SELECT FORMAT(sum(`cost`),2) as `b1`
FROM `outgoing`
WHERE `business`=1 AND active = 'yes'
GROUP BY business
) AS b1,
(
SELECT FORMAT(sum(`cost`),2) as `b1`
FROM `outgoing`
WHERE `business`=2 AND active = 'yes'
GROUP BY business
) AS b2
if you need the format
b1 | b2
300| 500
SELECT business, SUM(cost)
FROM mytable
GROUP BY
business
Try
SELECT business, SUM(cost) AS totalCost FROM myTable GROUP BY business
you can try this:
select
#num1:=(select sum(actor_id) from actor where actor_id%2=0)as number_1,
#num2:=(select sum(actor_id) from actor where actor_id%2!=0)as number_2,
#num1+#num2 as TOTAL;
or if you need active.
select
#num1:=(select sum(actor_id) from actor where actor_id%2=0 and active='yes')as number_1,
#num2:=(select sum(actor_id) from actor where actor_id%2!=0 and active='yes')as number_2,
#num1+#num2 as TOTAL;
I have the following database
id | user | urgency | problem | solved
The information in there has different users, but these users all have multiple entries
1 | marco | 0 | MySQL problem | n
2 | marco | 0 | Email problem | n
3 | eddy | 0 | Email problem | n
4 | eddy | 1 | MTV doesn't work | n
5 | frank | 0 | out of coffee | y
What I want to do is this: Normally I would check everybody's oldest problem first. I use this query to get the ID's of the oldest problem.
select min(id) from db group by user
this gives me a list of the oldest problem ID's. But I want people to be able to make a certain problem more urgent. I want the ID with the highest urgency for each user, or ID of the problem with the highest urgency
Getting the max(urgency) won't give the ID of the problem, it will give me the max urgency.
To be clear: I want to get this as a result
row | id
0 | 1
1 | 4
The last entry should be in the results since it's solved
Select ...
From SomeTable As T
Join (
Select T1.User, Min( T1.Id ) As Id
From SomeTable As T1
Join (
Select T2.User, Max( T2.Urgency ) As Urgency
From SomeTable As T2
Where T2.Solved = 'n'
Group By T2.User
) As MaxUrgency
On MaxUrgency.User = T1.User
And MaxUrgency.Urgency = T1.Urgency
Where T1.Solved = 'n'
Group By T1.User
) As Z
On Z.User = T.User
And Z.Id = T.Id
There are lots of esoteric ways to do this, but here's one of the clearer ones.
First build a query go get your min id and max urgency:
SELECT
user,
MIN(id) AS min_id,
MAX(urgency) AS max_urgency
FROM
db
GROUP BY
user
Then incorporate that as a logical table into
a larger query for your answers:
SELECT
user,
min_id,
max_urgency,
( SELECT MIN(id) FROM db
WHERE user = a.user
AND urgency = a.max_urgency
) AS max_urgency_min_id
FROM
(
SELECT
user,
MIN(id) AS min_id,
MAX(urgency) AS max_urgency
FROM
db
GROUP BY
user
) AS a
Given the obvious indexes, this should be pretty efficient.
The following will get you exactly one row back -- the most urgent, probably oldest problem in your table.
select id from my_table where id = (
select min(id) from my_table where urgency = (
select max(urgency) from my_table
)
)
I was about to suggest adding a create_date column to your table so that you could get the oldest problem first for those problems of the same urgency level. But I'm now assuming you're using the lowest ID for that purpose.
But now I see you wanted a list of them. For that, you'd sort the results by ID:
select id from my_table where urgency = (
select max(urgency) from my_table
) order by id;
[Edit: Left out the order by!]
I forget, honestly, how to get the row number. Someone on the interwebs suggests something like this, but no idea if it works:
select #rownum:=#rownum+1 ‘row', id from my_table where ...