I try to count rows from a group by result.
I want to count the number of exercise where there muscle is 1
My problem is that the count ignores the group by.
I want to use this:
SELECT COUNT(id) FROM soFitTest.users_program
where user_name = 1127 AND muscle = 1
group by exercise;
In my count I get 3, but when I run the query without this count I get only 1 row.
See the attached image.
If you are just trying to count the rows, then try " count(*) ", instead of specifying "id" in count function.
SELECT COUNT(*) FROM soFitTest.users_program where user_name = 1127 AND muscle = 1;
Hope this helps.
The first query from your image is invalid according to the SQL standard:
SELECT *
FROM soFitTest.users_program
WHERE user_name = 1127 AND muscle = 1
GROUP BY exercise
It happens that MySQL accepts it and produces a result but the values it returns are not determined. It is explained in the documentation page about how MYSQL handles GROUP BY.
The same query could produce a different result if the rows in the table are stored in a different order on the physical storage.
You should run:
SELECT *
FROM soFitTest.users_program
WHERE user_name = 1127 AND muscle = 1
i.e. without GROUP BY to see what rows match the conditions, before being aggregate by GROUP BY.
Then, when you the add GROUP BY clause, put in the SELECT clause only:
columns that appear in the GROUP BY clause - exercise for example;
GROUP BYaggregate functions - they combine the values from all the rows in a group to produce a single value; COUNT(*) for example will count the number of rows in each group;
you can add columns that are functionally-dependent on columns that appear in the GROUP BY clause; in plain English this means that if exercise is the PK of table users_program then you can use any other column of that table because its value is determined by the value of column exercise; but this is only if exercise is the PK (which is probably not the case here).
In conclusion, the query you probably want is:
SELECT exercise, COUNT(*)
FROM soFitTest.users_program
WHERE user_name = 1127 AND muscle = 1
GROUP BY exercise
It filters the rows that have user_name = 1127 AND muscle = 1 then makes groups out of them. Each group contains all the rows that have the same value in column exercise. From each group it produces a single row into the returned result set. The row contains the value of column exercise (which is the same for all rows in the group) and the number of rows in the group (COUNT(*)).
If you want to get count of exercices, your query is correct:
SELECT COUNT(1) FROM soFitTest.users_program where user_name = 1127 AND muscle = 1;
(COUNT(1) gives same result as COUNT(*) but doesn't try to retrieve all fields from DB - it's more efficient)
And if you need to get all rows with those criteria, you must skip GROUP BY:
SELECT * FROM soFitTest.users_program where user_name = 1127 AND muscle = 1
How about this:
SELECT COUNT(DISTINCT(exercise)) FROM ......
The answer is :
SELECT COUNT(t1.id) FROM
(SELECT id FROM soFitTest.users_program
where user_name = 1127 AND muscle = 1 group by exercise) t1;
Related
I have a table user_comission_configuration_history and I need to select the last Comissions configuration from a user_id.
Tuples:
I'm trying with many queries, but, the results are wrong. My last SQL:
SELECT *
FROM(
SELECT * FROM user_comission_configuration_history
ORDER BY on_date DESC
) AS ordered_history
WHERE user_id = 408002
GROUP BY comission_id
The result of above query is:
But, the correct result is:
id user_id comission_id value type on_date
24 408002 12 0,01 PERCENTUAL 2014-07-23 10:45:42
23 408002 4 0,03 CURRENCY 2014-07-23 10:45:41
21 408002 6 0,015 PERCENTUAL 2014-07-23 10:45:18
What is wrong in my SQL?
This is your query:
SELECT *
FROM (SELECT *
FROM user_comission_configuration_history
ORDER BY on_date DESC
) AS ordered_history
WHERE user_id = 408002
GROUP BY comission_id;
One major problem with your query is that it uses a MySQL extension to group by that MySQL explicitly warns against. The extension is the use of other columns in the in theselect that are not in the group by or in aggregation functions. The warning (here) is:
MySQL extends the use of GROUP BY so that the select list can refer to
nonaggregated columns not named in the GROUP BY clause. This means
that the preceding query is legal in MySQL. You can use this feature
to get better performance by avoiding unnecessary column sorting and
grouping. However, this is useful primarily when all values in each
nonaggregated column not named in the GROUP BY are the same for each
group. The server is free to choose any value from each group, so
unless they are the same, the values chosen are indeterminate.
So, the values returned in the columns are indeterminate.
Here is a pretty efficient way to get what you want (with "comission" spelled correctly in English):
SELECT *
FROM user_commission_configuration_history cch
WHERE NOT EXISTS (select 1
from user_commission_configuration_history cch2
where cch2.user_id = cch.user_id and
cch2.commission_id = cch.commission_id and
cch2.on_date > cch.on_date
) AND
cch.user_id = 408002;
Here's one way to do what your trying. It gets the max date for each user_ID and commissionID and then joins this back to the base table to limit the results to just the max date for each commissionID.
SELECT *
FROM user_comission_configuration_history A
INNER JOIN (
SELECT User_ID, Comission_Id, max(on_Date) mOn_Date
FROM user_comission_configuration_history
Group by User-Id, Comission_Id
) B
on B.User_ID = A.User_Id
and B.Comission_Id = A.Comission_ID
and B.mOnDate=A.on_date
WHERE user_id = 408002
ORDER BY on_Date desc;
I have joined 3 tables in my query. In my Inventory db,Price is taken from table c and quantity is taken from table b. How can I show the records list of users who have ordered between the given value and maximum value of the column.
I am using below query in mysql to retrieve records. As expected it shows error. Any help will be highly appreciated
SELECT .... GROUP BY userid HAVING SUM(c.`price` * b.`quantity`) BETWEEN 9000 AND MAX(SUM(c.`price` * b.`quantity`))
If I understand correctly you don't need BETWEEN. Try it this way
SELECT ....
GROUP BY userid
HAVING SUM(c.`price` * b.`quantity`) >= 9000
In case you wondered you can't chain aggregate functions. And even if you could it wouldn't make sense because you group by userid, but trying to get MAX of SUM from all users. In order for this to work you should've used a subquery to get max value e.g.
SELECT ....
GROUP BY userid
HAVING SUM(c.`price` * b.`quantity`) =
(
SELECT MAX(total) total
FROM
(
SELECT SUM(c.`price` * b.`quantity`) total
GROUP BY userid
) q
)
I have two tables:
Members:
id username
Trips:
id member_id flag_status created
("YES" or "NO")
I can do a query like this:
SELECT
Trip.id, Trip.member_id, Trip.flag_status
FROM
trips Trip
WHERE
Trip.member_id = 1711
ORDER BY
Trip.created DESC
LIMIT
3
Which CAN give results like this:
id member_id flag_status
8 1711 YES
9 1711 YES
10 1711 YES
My goal is to know if the member's last three trips all had a flag_status = "YES", if any of the three != "YES", then I don't want it to count.
I also want to be able to remove the WHERE Trip.member_id = 1711 clause, and have it run for all my members, and give me the total number of members whose last 3 trips all have flag_status = "YES"
Any ideas?
Thanks!
http://sqlfiddle.com/#!2/28b2d
In that sqlfiddle, when the correct query i'm seeking runs, I should see results such as:
COUNT(Member.id)
2
The two members that should qualify are members 1 and 3. Member 5 fails because one of his trips has flag_status = "NO"
You could use GROUP_CONCAT function, to obtain a list of all of the status ordered by id in ascending order:
SELECT
member_id,
GROUP_CONCAT(flag_status ORDER BY id DESC) as status
FROM
trips
GROUP BY
member_id
HAVING
SUBSTRING_INDEX(status, ',', 3) NOT LIKE '%NO%'
and then using SUBSTRING_INDEX you can extract only the last three status flags, and exclude those that contains a NO. Please see fiddle here. I'm assuming that all of your rows are ordered by ID, but if you have a created date you should better use:
GROUP_CONCAT(flag_status ORDER BY created DESC) as status
as Raymond suggested. Then, you could also return just the count of the rows returned using something like:
SELECT COUNT(*)
FROM (
...the query above...
) as q
Although I like the simplicity of fthiella's solution, I just can't think of a solution that depends so much on data representation. In order not to depend on it you can do something like this:
SELECT COUNT(*) FROM (
SELECT member_id FROM (
SELECT
flag_status,
#flag_index := IF(member_id = #member, #flag_index + 1, 1) flag_index,
#member := member_id member_id
FROM trips, (SELECT #member := 0, #flag_index := 1) init
ORDER BY member_id, id DESC
) x
WHERE flag_index <= 3
GROUP BY member_id
HAVING SUM(flag_status = 'NO') = 0
) x
Fiddle here. Note I've slightly modified the fiddle to remove one of the users.
The process basically ranks the trips for each of the members based on their id desc and then only keeps the last 3 of them. Then it makes sure that none of the fetched trips has a NO in the flag_status. FInally all the matching meembers are counted.
I have a table with many integers in column named 'data'
data | param
123 1
432 1
123 1
423 2
234 1
423 2
I have a query
SELECT data FROM data_table WHERE param=*something* GROUP BY data
ORDER BY rand() LIMIT 1
That returns a random distinct integer from the table. But I also need to get the total number of integers that I was choosing from. I tried:
SELECT DISTINCT(data) AS data, COUNT(DISTINCT(data)) as count FROM
data_table WHERE param=*something* ORDER BY rand() LIMIT 1
This returns correct number from which data was chosen, but the data returned is no random - it is always the same row. So I need to get number of rows that rand() were selected after WHERE was applied. So making a query on above table should return:
query WHERE param='1':
data count
123 3
query WHERE param='1':
data count
432 3
query WHERE param='1':
data count
234 3
query WHERE param='2':
data count
423 1
This works. I normally don't recommend putting a query in the selector because it evaluates for each row returned. However in this case you are only returning one row so it is OK.
select
count(distinct data) as cnt,
(SELECT data FROM data_table GROUP BY data
WHERE param='xxx'
ORDER BY rand() LIMIT 1) as random
from data_table
WHERE param='xxx'
See this SQL Fiddle to see it work without the where statements.
I think this situation needs to be split in two steps:
Select the random entry where param has the value you want
Count the entries of the data
I propose this solution
set #yourParam = 1; -- Put here the parameter value you want to filter
select
data,
(select count(distinct date) from data_table where param=#yourParam) as `count`
from
data_table
where
param = #yourParam
order by
rand()
limit 1;
Hope this helps you
try this
select
data, (select count(distinct data) from data_table where param=1) as `count`
from
data_table where param = 1
order by rand()
limit 1
DEMO HERE
I think the easiest is to join another select statement to get the total number of rows and add that to your main SELECT statement.
SELECT data AS data, count.count
FROM data
JOIN (SELECT COUNT(DISTINCT(data)) AS count FROM data WHERE parameter = "test") AS count
WHERE parameter = "test"
ORDER BY rand()
LIMIT 1;
Here's a SQL Fiddle
I would like to determine two things from a single query:
Most prevalent column in a table
The amount of times such column was located upon querying the table
Example Table:
user_id some_field
1 data
2 data
1 data
The above would return user_id # 1 as being the most prevalent in the table, and it would return (2) for the total amount of times that it was located in the table.
I have done my research and I came across two types of queries.
GROUP BY user_id ORDER BY COUNT(*) DESC
SUM
The problem is that I can't figure out how to use these two queries in conjunction with one another. For example, consider the following query which successfully returns the most prevalent column.
$top_user = "SELECT user_id FROM table_name GROUP BY user_id ORDER BY COUNT(*) DESC";
The above query returns "1" based on the example table shown above. Now, I would like to be able to return "2" for the total amount of times the user_id (1) was found in the table.
Is this by any chance possible?
Thanks,
Evan
You can include count(*) in the SELECT list:
SELECT user_id, count(*) as totaltimes from table_name
GROUP BY user_id ORDER BY count(*) DESC;
If you want only the first one:
SELECT user_id, count(*) as totaltimes from table_name
GROUP BY user_id ORDER BY count(*) DESC LIMIT 1;