SQL requires aggregate function over singular value - sql

I have table language that contains the columns country, name and percentage.
A sample set might look like this:
+---------+---------+------------+
| country | name | percentage |
+---------+---------+------------+
| usa | english | 85 |
| usa | spanish | 10 |
| usa | german | 5 |
| germany | german | 100 |
+---------+---------+------------+
I want to get
+---------+---------+------------+
| country | name | percentage |
+---------+---------+------------+
| usa | english | 85 |
| germany | german | 100 |
+---------+---------+------------+
select country, name, max(percentage) from language group by country
Tells me that I need to put all but one columns into either a aggregation function or the group by.
If you put the name into the group by, you get the original table, since all pairs of country and name are unique.
Name should be a single specific value since there can only be one pair of country and maximum percentage, so there's nothing to compare it too and it's a string anyway.
I'm sure there's a simple way to resolve this, without doing any second select statements and joining tables and the like.

If you want the maximum percentage, use row_number():
select l.*
from (select l.*,
row_number() over (partition by country order by percentage desc) as seqnum
from language l
) l
where seqnum = 1;

Related

How to find the number of identical rows in a column other than the group by group by SQL statement

An easy problem to explain with an example:
I have this table:
Country | Name
------------------------------
US | A
US | B
US | A
US | A
FR | A
FR | C
FR | C
And I want as result:
Country | Name | Nname
------------------------------
US | A | 3
US | B | 1
FR | A | 1
FR | C | 2
I use posgres, how can I do?
Just a simple GROUP BY for this:
SELECT country, name, count(*) as nname
FROM table
GROUP BY country, name;
check the below
SELECT COUNTRY, NAME, COUNT(NAME) as nname
FROM THIS_TABLE GROUP BY country, name

How to select a single row from an sql table with multiple rows having same value in a column

I have an sql table which current looks like this:
id | Name | Age| City
______________________________
1 | Mike | 26 | New York
2 | Nick | 32 | London
3 | Anne | 22 | New York
4 | Andy | 24 | Lagos
5 | Nickie | 27 | Paris
6 | Sam | 26 | London
I need to query the table to return something like:
id | Name | Age| City
______________________________
1 | Mike | 26 | New York
2 | Nick | 32 | London
3 | Andy | 24 | Lagos
4 | Nickie | 27 | Paris
so that all rows with same value for a particular column (city in this example) gets returned just once (only 1 of multiple rows with same column values gets returned). If i add a timestamp column, then i want only the latest row displayed. How do i write this sql
you can write required query like below if you have a column date_edited with type TIMESTAMP .
SET ##sql_mode='ONLY_FULL_GROUP_BY';
SELECT Name, Age,
GROUP_CONCAT(DISTINCT City ORDER BY date_edited DESC) AS city
FROM TABLE_NAME
GROUP BY City
ORDER BY date_edited DESC
SELECT Name, Age, City, MAX(TIME_STAMP_COLUMN) FROM YOUR_TABLE GROUP BY City;
This query will select all your rows, group them by your City column to remove duplicates, then return the row for each grouped city that has the greatest, or most recent, time stamp associated with it.
In most databases, you would use the ANSI-standard row_number() function:
select t.*
from (select t.*, row_number() over (partition by city order by city) as seqnum
from t
) t
where seqnum = 1;
You would use order by timestamp desc if you wanted the latest column.
Disable only_full_group_by if you are on WAMP by following this sequence:
Left click on WAMP Icon, MySQL, MySQL settings, SQL mode, User mode. then restart your WAMP services. Then try your SQL after services restarted

Aggregate functions in where clause MS Access

I have multiples tables with Names and Ages like this:
| Name | Age |
------------------
| Carlos | 25 |
| Mauricio | 28 |
| Cesar | 19 |
| Hernan | 7 |
And I need to retrieve all the names that are above the average Age.
I tried
select Name from Table1 where Age > avg(Age)
but I found that the where clause does not work with aggregate functions, so I tried
select Name from Table 1 having Age > avg(Age)
But it does not work either.
You can do it with following query:
select Name from Table1 where Age > (select avg(Age) from Table1)

Count number of records in subgroup while keeping a number of records in a group

I have a table with the following structure (it's a simplified version, just to show the idea):
name | city
------------------
John | New York
Thomas | Berlin
Hans | Berlin
Boris | Moscow
Boris | Moscow
Vasiliy | Moscow
I can use group by to get a total number of people in every city, like so:
select count(*) from my_table group by city
But I need a little bit more and I can' wrap my head around it: I need to get a number of all people with the same name in the same city while keeping a total number of people in that city. This is how the result should look like:
name | totalWithThisName | totalInThisCity | city
--------------------------------------------------------
John | 1 | 1 | New York
Thomas | 1 | 2 | Berlin
Hans | 1 | 2 | Berlin
Boris | 2 | 3 | Moscow
Vasiliy | 1 | 3 | Moscow
I know that I can take a raw data from db, and make calculations in my java program, but it would be great to make it in a plain SQL.
Update: I'm using mysql and I can't use over clause.
select distinct name
, count(*) over (partition by Name) as TotalWithThisName
, count(*) over (partition by City) as TotalInThisCity
, city
from YourTable
The solution I've made so far is to use subquery with join. It looks like this:
select
name,
city,
count(*) as totalWithThisName,
T.totalInThisCity
from
my_table
join (select
count(*) as totalInThisCity,
city
from
my_table
group by city) T on my_table.city = T.city
group by
city, name;

How to use count and group by at the same select statement

I have an SQL SELECT query that also uses a GROUP BY,
I want to count all the records after the GROUP BY clause filtered the resultset.
Is there any way to do this directly with SQL? For example, if I have the table users and want to select the different towns and the total number of users:
SELECT `town`, COUNT(*)
FROM `user`
GROUP BY `town`;
I want to have a column with all the towns and another with the number of users in all rows.
An example of the result for having 3 towns and 58 users in total is:
Town
Count
Copenhagen
58
New York
58
Athens
58
This will do what you want (list of towns, with the number of users in each):
SELECT `town`, COUNT(`town`)
FROM `user`
GROUP BY `town`;
You can use most aggregate functions when using a GROUP BY statement
(COUNT, MAX, COUNT DISTINCT etc.)
Update:
You can declare a variable for the number of users and save the result there, and then SELECT the value of the variable:
DECLARE #numOfUsers INT
SET #numOfUsers = SELECT COUNT(*) FROM `user`;
SELECT DISTINCT `town`, #numOfUsers FROM `user`;
You can use COUNT(DISTINCT ...) :
SELECT COUNT(DISTINCT town)
FROM user
The other way is:
/* Number of rows in a derived table called d1. */
select count(*) from
(
/* Number of times each town appears in user. */
select town, count(*)
from user
group by town
) d1
Ten non-deleted answers; most do not do what the user asked for. Most Answers mis-read the question as thinking that there are 58 users in each town instead of 58 in total. Even the few that are correct are not optimal.
mysql> flush status;
Query OK, 0 rows affected (0.00 sec)
SELECT province, total_cities
FROM ( SELECT DISTINCT province FROM canada ) AS provinces
CROSS JOIN ( SELECT COUNT(*) total_cities FROM canada ) AS tot;
+---------------------------+--------------+
| province | total_cities |
+---------------------------+--------------+
| Alberta | 5484 |
| British Columbia | 5484 |
| Manitoba | 5484 |
| New Brunswick | 5484 |
| Newfoundland and Labrador | 5484 |
| Northwest Territories | 5484 |
| Nova Scotia | 5484 |
| Nunavut | 5484 |
| Ontario | 5484 |
| Prince Edward Island | 5484 |
| Quebec | 5484 |
| Saskatchewan | 5484 |
| Yukon | 5484 |
+---------------------------+--------------+
13 rows in set (0.01 sec)
SHOW session status LIKE 'Handler%';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| Handler_commit | 1 |
| Handler_delete | 0 |
| Handler_discover | 0 |
| Handler_external_lock | 4 |
| Handler_mrr_init | 0 |
| Handler_prepare | 0 |
| Handler_read_first | 3 |
| Handler_read_key | 16 |
| Handler_read_last | 1 |
| Handler_read_next | 5484 | -- One table scan to get COUNT(*)
| Handler_read_prev | 0 |
| Handler_read_rnd | 0 |
| Handler_read_rnd_next | 15 |
| Handler_rollback | 0 |
| Handler_savepoint | 0 |
| Handler_savepoint_rollback | 0 |
| Handler_update | 0 |
| Handler_write | 14 | -- leapfrog through index to find provinces
+----------------------------+-------+
In the OP's context:
SELECT town, total_users
FROM ( SELECT DISTINCT town FROM canada ) AS towns
CROSS JOIN ( SELECT COUNT(*) total_users FROM canada ) AS tot;
Since there is only one row from tot, the CROSS JOIN is not as voluminous as it might otherwise be.
The usual pattern is COUNT(*) instead of COUNT(town). The latter implies checking town for being not null, which is unnecessary in this context.
With Oracle you could use analytic functions:
select town, count(town), sum(count(town)) over () total_count from user
group by town
Your other options is to use a subquery:
select town, count(town), (select count(town) from user) as total_count from user
group by town
If you want to order by count (sound simple but i can`t found an answer on stack of how to do that) you can do:
SELECT town, count(town) as total FROM user
GROUP BY town ORDER BY total DESC
You can use DISTINCT inside the COUNT like what milkovsky said
in my case:
select COUNT(distinct user_id) from answers_votes where answer_id in (694,695);
This will pull the count of answer votes considered the same user_id as one count
I know this is an old post, in SQL Server:
select isnull(town,'TOTAL') Town, count(*) cnt
from user
group by town WITH ROLLUP
Town cnt
Copenhagen 58
NewYork 58
Athens 58
TOTAL 174
If you want to select town and total user count, you can use this query below:
SELECT Town, (SELECT Count(*) FROM User) `Count` FROM user GROUP BY Town;
if You Want to use Select All Query With Count Option, try this...
select a.*, (Select count(b.name) from table_name as b where Condition) as totCount from table_name as a where where Condition
Try the following code:
select ccode, count(empno)
from company_details
group by ccode;