How to tally column values of multiple rows with pure mysql? - mysql

hypothetic tables
user_id | hits
Can I get MySQL to return the total hits of a Select query? I know i could add them together with php or similar, just wondering if there is a pure MySQL way?

Total hits per user
SELECT userId, Sum(Hits)
FROM Table
GROUP by userId
OR
Total hits
SELECT Sum(Hits)
FROM Table

select sum(hits) from ...

Depending on the specific SQL query you're using you could either SUM a column or potentially use the 'WITH ROLLUP' GROUP modifier if you require a query-wide total.

Related

Mysql DISTINCT with more than one column (remove duplicates)

My database is called: (training_session)
I try to print out some information from my data, but I do not want to have any duplicates. I do get it somehow, may someone tell me what I do wrong?
SELECT DISTINCT athlete_id AND duration FROM training_session
SELECT DISTINCT athlete_id, duration FROM training_session
It works perfectly if i use only one column, but when I add another. it does not work.
I think you misunderstood the use of DISTINCT.
There is big difference between using DISTINCT and GROUP BY.
Both have some sort of goal, but they have different purpose.
You use DISTINCT if you want to show a series of columns and never repeat. That means you dont care about calculations or group function aggregates. DISTINCT will show different RESULTS if you keep adding more columns in your SELECT (if the table has many columns)
You use GROUP BY if you want to show "distinctively" on a certain selected columns and you use group function to calculate the data related to it. Therefore you use GROUP BY if you want to use group functions.
Please check group functions you can use in this link.
https://dev.mysql.com/doc/refman/8.0/en/group-by-functions.html
EDIT 1:
It seems like you are trying to get the "latest" of a certain athlete, I'll assume the current scenario if there is no ID.
Here is my alternate solution:
SELECT a.athlete_id ,
( SELECT b.duration
FROM training_session as b
WHERE b.athlete_id = a.athlete_id -- connect
ORDER BY [latest column to sort] DESC
LIMIT 1
) last_duration
FROM training_session as a
GROUP BY a.athlete_id
ORDER BY a.athlete_id
This syntax is called IN-SELECT subquery. With the help of LIMIT 1, it shows the topmost record. In-select subquery must have 1 record to return or else it shows error.
MySQL's DISTINCT clause is used to filter out duplicate recordsets.
If your query was SELECT DISTINCT athlete_id FROM training_session then your output would be:
athlete_id
----------
1
2
3
4
5
6
As soon as you add another column to your query (in your example, the column called duration) then each record resulting from your query are unique, hence the results you're getting. In other words the query is working correctly.

How to remove a subquery from the FROM field in MySQL

I'm new to MySQL and databases and I've seen in many places that it is not considered a good programming practice to use subqueries in the FROM field of SELECT in MySQL, like this:
select userid, avg(num_pages)
from (select userid , pageid , regid , count(regid) as num_pages
from reg_pag
where ativa = 1
group by userid, pageid) as from_query
group by userid;
which calculates the average number of registers per page that the users have.
The reg_page table looks like this:
Questions:
How to change the query so that it doesn't use the subquery in the FROM field?
And is there a general way to "flatten" queries like this?
The average number of registers per page per user can also be calculated as number of registers per user divided by number of pages per user. Use count distinct to count only distinct psgeids per user:
select userid, count(regid) / count(distinct pageid) as avg_regs
from reg_pag
where ativa=1
group by userid;
There is no general way of flattening such queries. It may not even be possible to flatten some of them, otherwise there would be little point in having this feature in the first place. Do not get scared of using subqueries in the from clause, in some occasions they may be even more effective, than a flattened query. But this is vendor and even version specific.
One way is to use count(distinct):
select userid, count(*) / count(distinct pageid)
from reg_pag
where ativa = 1
group by userid;

Saving time in queries on sql

I have a scenario. I have say 300 records in my table. I execute a query to get the total count. Then , since i have to implement pagination,
I select the data from the same table using limits according t the count. I was thinking if i can get the count and data in a single query.? .
I tried below code:
Select * ,count(*) as cnt from table;
But this gave me the total count but only 1 record!
Is there a way to save my time exhausted in query and get results in a single query?
something like:
select t1.*,t2.cnt
from table t1
cross join (select count(*) as cnt from table) t2
limit 'your limit for the first page'
or
select *,(select count(*) from table) as cnt
from table
limit 'your limit for the first page'
You can get information in data structure you mentioned, but there is really no reason to do it. There is no performance problem when you do two queries - one for getting rows count and another for data selection. You don't save anything when you try to select all information in one query. Do two simple queries instead, it will be better solution for your app - you will preserve its simplicity and clarity.
Using two queries might not be as bad as you may think, you can read this for more information.

Is it wrong to have count(*) as part of the select query

select id, first_name, count(*) from users;
The users table contains 10 entries, but the above select query shows only a single row. Is it wrong to mix count(*) as part of the above query?
COUNT is a function that aggregates. You can't mix it into your normal query.
If you want to receive the ten entries just do a normal select:
SELECT id, name FROM users;
and to get the number of entries:
SELECT COUNT(id) FROM users;
Its becuase you are using an aggregate function in the select part of the query,
to return the 10 records you just need the id, and first_name in the query.
EG:
SELECT id, first_Name
FROM users
if you wanted to get a count of the records in the table then you could use
SELECT (Count(id))
FROM [users]
It's not "wrong", but it is meaningless without a "group by" clause - most databases will reject that query, as aggregate functions should include a group by if you're including other columns.
Not sure exactly what you're trying to achieve with this?
select id, first_name,(select count(*) from users) AS usercount from users;
will give each individual user and the total count but again, not sure why you would want it.
select id, first_name from users,(select count(*) as total from users) as t;
COUNT is an aggregate function and it will always give you count of all records in table unless used in combination with group by.
If you use it in combination with normal query, then it will take priority in deciding the final output as in your case it returns 1.
If you want to return all 10 records, you should just write -
select id,first_name from users
If you need number of rows in a table, you can use MySQL's SQL_CALC_FOUND_ROWS clause. Check MySQL docs to see how it's used.

SQL how to count all rows up to a max value

I am having trouble counting the number of rows until it reaches a certain PK.
My PK is called id and I want to count all rows until i reach a specified id
I have tried using this query but it doesn't work probably becuase I am using a MySQL table
select max(count(*)) from news where id=18 group by id
I get this error
Invalid use of group function
select count(*) from news where id<=18
I would use the following:
select count(id) from news where id <= 18
This will be more efficient as you are only returning one column in a row as opposed to all of them.