Counting how many items are repeated 1, 2 or 3 times - sql

I have values
Contractor_Key
--
AAA
BBB
CCC
BBB
CCC
CCC
DDD
CCC
In this example, AAA and DDD repeated just once, this means that count of once repeated values is 2. BBB repeated twice and twice repeated items count here is just 1.
exactly tree times repeated values there are not at all and I don't want output CCC because it repeated more than 3 times.
I need calculate, how many values I have, which repeated exactly once, twice or three times.
I know this is something by using grouping, but don't realize how to get desirable result

Use two levels of aggregation:
select cnt, count(*), min(Contractor_Key), max(Contractor_Key)
from (select Contractor_Key, count(*) as cnt
from t
group by Contractor_Key
) c
group by cnt
order by cnt;
I call this a "histogram-of-histgrams" query. I include two examples of keys for each count for further investigation.

SELECT item_repeated_quantity, COUNT(*) FROM (
SELECT Contractor_Key, COUNT(*) AS item_repeated_quantity from t group by Contractor_Key HAVING COUNT(*) <= 3
)t
GROUP BY item_repeated_quantity
ORDER BY item_repeated_quantity

I think you want to do aggregation twice - first to find count for each contractor_key and then find count for each value of count (found in first aggregation):
select cnt,
count(*) as times
from (
select count(*) cnt
from your_table
group by contractor_key
) t
group by cnt;

Try this
;WITH CTE
AS
(
SELECT
Contractor_Key,
Cnt = COUNT(1)
FROM MyTable
GROUP BY Contractor_Key
)
SELECT
Cnt,
COUNT(1)
FROM CTE

Related

COUNT of GROUP of two fields in SQL Query -- Postgres

I have a table in postgres with 2 fields: they are columns of ids of users who have looked at some data, under two conditions:
viewee viewer
------ ------
93024 66994
93156 93151
93163 113671
137340 93161
92992 93161
93161 93135
93156 93024
And I want to group them by both viewee and viewer field, and count the number of occurrences, and return that count
from high to low:
id count
------ -----
93161 3
93156 2
93024 2
137340 1
66994 1
92992 1
93135 1
93151 1
93163 1
I have been running two queries, one for each column, and then combining the results in my JavaScript application code. My query for one field is...
SELECT "viewer",
COUNT("viewer")
FROM "public"."friend_currentfriend"
GROUP BY "viewer"
ORDER BY count DESC;
How would I rewrite this query to handle both fields at once?
You can combine to columns from the table into a single one by using union all then use group by as below:
select id ,count(*) Count from (
select viewee id from vv
union all
select viewer id from vv) t
group by id
order by count(*) desc
Results:
This is a good place to use a lateral join:
select v.viewx, count(*)
from t cross join lateral
(values (t.viewee), (t.viewer)) v(viewx)
group by v.viewx
order by count(*) desc;
You can try this :
SELECT a.ID,
SUM(a.Total) as Total
FROM (SELECT t.Viewee AS ID,
COUNT(t.Viewee) AS Total
FROM #Temp t
GROUP BY t.Viewee
UNION
SELECT t.Viewer AS ID,
COUNT(t.Viewer) AS Total
FROM #Temp t
GROUP BY t.Viewer
) a
GROUP BY a.ID
ORDER BY SUM(a.Total) DESC

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.

How to get count of records satisfying multipel critierias in SQL Server?

I have an sql table with the below columns
OrderNo, GroupNum, ShipMethod, TrackingNo
I want to find number of orders that have multiple 'ShipMethod' for same groupnum?
Sample records wourld be:
Order123 1 DHL
Order123 2 DHL1
Order123 2 Fedex
Then i need to get result stating 2 or if possible output as below:
OrderNumer GroupNum Count
---------- ------- -----
Order123 2 2 (Because 2 shipmethods)
Group by the columns you want to be unique, use count() to get each groups count and use having to limit the output to only the relevant groups
select ordernum, groupnum, count(*) as cnt
from your_table
group by ordernum, groupnum
having count(*) > 1
If I understand correctly:
select OrderNumer, groupnum, count(*)
from t
group by OrderNumer, groupnum
having count(*) > 1;
You may also want count(distinct shipmethod), if you want to count the distinct values rather than the number of rows.

Replace nested query to single select query

Consider the table fields as follows.
Appid Client_name is_real RTT
100 C1 1 1
200 C1 1 6
200 C2 1 7
100 C1 1 9
200 C1 0 7
Now I need total number of unique real Appid's in the table. We can say one appid record is real by if 'is_real' is 1.
In above table, we have only 3 real Appid's. Which are (100,C1), (200,C1) and (200, C2).
Postgesql command:
Select sum(r)
from (select count(is_real) as r from table group by Appid, Client_name) as t;
I don't want any recursive query. If you can fetch with single select query, it would be helpful.
Since you seem to define a unique id by (Appid, Client_name) (which is confusing, since you are mixing terms):
SELECT COUNT(DISTINCT (Appid, Client_name)) AS ct
FROM tbl
WHERE is_real = 1;
(Appid, Client_name) is a row-type expression, short for ROW(Appid, Client_name). Only distinct combinations are counted.
Another trick to get this done without subquery is to use a window function:
SELECT DISTINCT count(*) OVER () AS ct
FROM tbl
WHERE is_real = 1
GROUP BY Appid, Client_name;
But neither is going to be faster than using a subquery (which is not a recursive query):
SELECT count(*) AS ct
FROM (
SELECT 1
FROM tbl
WHERE is_real = 1
GROUP BY Appid, Client_name
) sub;
That's what I would use.
It's essential to understand the sequence of events in a SELECT query:
Best way to get result count before LIMIT was applied
total number of unique real Appid's in the table
I assume is_real is 1 = true, 0 = false.
SELECT COUNT(DISTINCT Appid)
FROM table
WHERE is_real = 1;

What exactly does SELECT DISTINCT(COUNT(*)) do?

I used the following query and it returned what I wanted it to return, but I'm having a tough time wrapping my head around what the query is doing.
Query is nothing fancier than what's in the title: select distinct(count(*)) from table1
Distinct is not required in your SQL ,as you are going to get only result, count(*) without group by clause returns, count of all rows within that table.
Hence try this :
select count(*) from table1
Distinct is used for finding distinct values from a group of values:
say you have table1 , with column1 as :
Column1
----------
a
a
b
b
a
c
following sqls are run you will get output as :
1) select count(*) from table1
output :6
2) select distinct(count(*)) from table1
output :6
3) select count( distinct column1) from table1
output :3
Usually distinct is used inside count preferably with a particular column .
select count( distinct column_name_n ) from table1
The distinct is redundant... Select Count(*) with only one table can only generate one value, so distinct (which would eliminate duplicates) is irelelvant.
If you had multiple outputs, (if for example you were grouping on something) then it would cause the query to only display one output row for every distinct value of count(*) that would other wise be generated...
if, for example, you had
name
Bob
Bob
Bob
Bob
Mary
Mary
Mary
Mary
Dave
Dave
Al
George
then
select count(*)
From table
group By name
would result in
4
4
2
1
1
but
select distinct count(*)
From table
group By name
would result in
4
2
1