How to get the smallest unique integer from a table in SQLite - sql

I have a table that has two columns, name and number. I'd like to get the smallest unique number from the provided table. for example
name
number
john
1
abbey
3
afton
2
mike
1
lucas
5
jack
2
jake
4
tony
3
For example, the smallest value here is 1 but the smallest unique value is 4
How could I make a query in SQLite that can do that?
I did see this post but it's not what I want
Edit: This is the code I tried
Select a.name, a.number
From Result a
Having count(a.smallest) = 1
Group By a.smallest;
It returned "Error: near line XX: near "Group": syntax error"
I also tried
Select a.name, a.number
From Result a
Where count(a.smallest) = 1
Group By a.smallest;
But it returned "Error: near line XX: misuse of aggregate: count()"

You may try aggregating your table by the number, restricting to numbers only appearing once, and then retaining the smallest number:
SELECT number
FROM yourTable
GROUP BY number
HAVING COUNT(*) = 1
ORDER BY number
LIMIT 1;

Using ROW_NUMBER:
SELECT *
FROM (SELECT a.*, COUNT(*) OVER(PARTITION BY number) AS cnt
FROM Result a) sub
WHERE cnt = 1
ORDER BY number
LIMIT 1;
Output:
name number cnt
jake 4 1
db<>fiddle demo

You can group by number and set the condition in the HAVING clause that the number is unique.
Then pick the smallest number with MIN() window function:
SELECT DISTINCT MIN(number) OVER () AS min_number
FROM tablename
GROUP BY number
HAVING COUNT(*) = 1;
See the demo.

Related

Oracle SQL how to find count less than avg

my code is like :
SELECT
number,
name,
count(*) as "the number of correct answer"
FROM
table1 NATURAL JOIN table2
WHERE
answer = 'T'
GROUP BY
number,
name
HAVING
count(*) < avg(count(*))
ORDER BY
count(*);
Here I want to find the group with count less than the average number of count for each group, but here I failed to use HAVING or WHERE, could anyone help me?
How can I only select the 1 name1 2 since avg of count is (2+6+7)/3 = 5 and only 2 is less than avg.
number name count
1 name1 2
2 name2 6
3 name3 7
I would advise you to never use natural joins. They obfuscate the query and make the query a maintenance nightmore.
You can use window functions:
SELECT t.*
FROM (SELECT number, name,
COUNT(*) as num_correct,
AVG(COUNT(*)) OVER () as avg_num_correct
FROM table1 JOIN
table2
USING (?). -- be explicit about the column name
WHERE answer = 'T'
GROUP BY number, name
) t
WHERE num_correct < avg_num_correct;
As with your version of the query, this filters out all groups that have no correct answers.
I would place your current query logic into a CTE, and then tag on the average count in the process:
WITH cte AS (
SELECT number, name, COUNT(*) AS cnt,
AVG(COUNT(*)) OVER () AS avg_cnt
FROM table1
NATURAL JOIN table2
WHERE answer = 'T'
GROUP BY number, name
)
SELECT number, name, cnt AS count
FROM cte
WHERE cnt < avg_cnt;
Here we are using the AVG() function as an analytic function, with the window being the entire aggregated table. This means it will find the average of the counts per group, across all groups (after aggregation). Window functions (almost) always evaluate last.

What is the difference between count (*) and count(attribute_name)?

Is there any difference between COUNT(*) and COUNT(attribute_name)?
I used count(attribute_name) as I thought that it would be specific hence the searching process would be easier. Is that true?
It would be great to see any example with sql code with my issue to help me understand better
Imagine this table:
select Count(TelephoneNumber) from Calls -- returns 3
select Count(*) from Calls -- returns 4
count(column_name) also counts duplicate values. Consider:
select Count(TelephoneNumber) from Calls -- returns 4
COUNT(*) counts all the records in the group.
COUNT(column_name) only counts non-null values.
There is also another typical expression, COUNT(DISTINCT column_name), that counts non-null distinct values.
Since you asked for it, here is a demo on DB Fiddlde:
with t as (
select 1 x from dual
union all select 1 from dual
union all select null from dual
)
select count(*), count(x), count(distinct x) from t
COUNT(*) | COUNT(X) | COUNT(DISTINCTX)
-------: | -------: | ---------------:
3 | 2 | 1
COUNT(*) will count all the rows.
COUNT(column) will count non-NULLs only.
Your can use of COUNT(*) or COUNT(column) which should be based on the desired output only.
Consider below Example of employee table
ID Name Description
1 Raji Smart
2 Rahi Positive
3
4 Falle Smart
select count(*) from employee;
Count(*)
4
select count(name) from employee;
Count(Name)
3
count() only counts non-null values. * references the complete row and as such never excludes any rows. count(attribute_name) only counts rows where that column is no null.
So this:
select count(attribute_name)
from the_table
is equivalent to:
select count(*)
from the_table
where attribute_name is not null
The difference is simple: COUNT(*) counts the number of rows produced by the query, whereas COUNT(1) counts the number of 1 values. Note that when you include a literal such as a number or a string in a query, this literal is "appended" or attached to every row that is produced by the FROM clause.
For more detail this link would help you understand.

Get Count Based on Combinations of Values from Second Column

I have a table format like below:
Id Code
1 A
1 B
2 A
3 A
3 C
4 A
4 B
I am trying to get count of code combinations like below:
Code Count
A,B 2 -- Row 1,2 and Row 6,7
A 1 -- Row 3
A,C 1 -- Row 4
I am unable to get the combination result. All I can do is group by but I am not getting count of IDs based in combinations.
You need to aggregate the rows, somehow, and do that twice. The code looks something like this:
select codes, count(*) as num_ids
from (select id, group_concat(code order by code) as codes
from t
group by id
) id
group by code;
group_concat() might be spelled listagg() or string_agg() depending on the database.
In SQL Server, use string_agg():
select codes, count(*) as num_ids
from (select id, string_agg(code, ',') within group (order by code) as codes
from t
group by id
) id
group by code;

SQL select top rows based on limit

Please help me t make below select query
Source table
name Amount
-----------
A 2
B 3
C 2
D 7
if limit is 5 then result table should be
name Amount
-----------
A 2
B 3
if limit is 8 then result table
name Amount
-----------
A 2
B 3
C 2
You can use window function to achieve this:
select name,
amount
from (
select t.*,
sum(amount) over (
order by name
) s
from your_table t
) t
where s <= 8;
The analytic function sum will be aggregated row-by-row based on the given order order by name.
Once you found sum till given row using this, you can filter the result using a simple where clause to find rows till which sum of amount is under or equal to the given limit.
More on this topic:
The SQL OVER() clause - when and why is it useful?
https://explainextended.com/2009/03/08/analytic-functions-sum-avg-row_number/

Grouping by number of occurrences of a repeatable value in Oracle SQL

Lets assume we have a table like this.
id name value
1 x 12
2 x 23
3 y 47
4 x 18
5 y 29
6 z 45
7 y 67
Doing a normal group by name would yield us
select name,count(*) from table group by name;
name count(*)
x 3
y 3
z 1
I want to get the reverse.. ie. grouping the number of names that occur a set number of times. I want my output to be
count number of elements occuring count times
1 1
3 2
Is it possible to do this using just a single query? Another way is to use a temp table but I dont want to do that.
Thanks
You need one more group by:
select cnt, count(*), min(name), max(name)
from (select name, count(*) as cnt
from table
group by name
) n
group by cnt
order by 1;
I do these types of histogram queries all the time. The min() and max() provide sample data. This is useful to understand outliers and unexpected values.
You can GROUP BY twice, e.g.
with
Names as (
select name as name,
count(1) as cnt
from MyTable
group by name)
select count(1),
cnt
from Names
group by cnt