How to get unique count without distinct - postgresql

I must count a number of unique surnames and names in the Postgresql table.
The problem is usage of distinct is denied by task.
What I tried to do:
SELECT COUNT(SURNAME), COUNT (NAME) FROM PEOPLE GROUP BY NAME, SURNAME;
Output:
1 1 1 1 1 and etc
(4939 rows)
But it looks like I did something wrong because in output I must get only two digits with a count.
Any idea what to do with it?

You can get around using DISTINCT by first grouping by the name or surname, and then taking a count of that intermediate table.
SELECT
(SELECT COUNT(*) FROM
(SELECT SURNAME FROM PEOPLE GROUP BY SURNAME) t) AS surname_cnt,
(SELECT COUNT(*) FROM
(SELECT NAME FROM PEOPLE GROUP BY NAME) t) AS name_cnt

Related

How do I make my RANK () OVER query work in select?

table image
I have this table that I need to sort in the following way:
need to rank Departments by Salary;
need to show if Salary = NULL - 'No data to be shown' message
need to add total salary paid to the department
need to count people in the department
SELECT RANK() OVER (
ORDER BY Salary DESC
)
,CASE
WHEN Salary IS NULL
THEN 'NO DATA TO BE SHOWN'
ELSE Salary
,Count(Fname)
,Total(Salary) FROM dbo.Employees
I get an error saying:
Column 'dbo.Employees.Salary' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Why so?
Column 'dbo.Employees.Salary' is invalid in the select list because it
is not contained in either an aggregate function or the GROUP BY
clause.
Why so?
The aggregate functions are returning a single value for the whole table, you can't SELECT a field alongside them it doesn't makes sense. Like say, you have a students table you apply Sum(marks) for the whole students table, and you are then also selecting student's name Select studentname in your query. Which student's name will the database engine select? Confusing
Column "invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause"
I tried this-
using inner query
SELECT RANK() OVER (ORDER BY SAL DESC) RANK,FNAME,DEPARTMENT
CASE
WHEN SAL IS NULL THEN 'NO DATA TO BE SHOWN'
ELSE SAL
END
FROM
(SELECT COUNT(FNAME) FNAME, SUM(SALARY) SAL, DEPARTMENT
FROM TESTEMPLOYEE
GROUP BY DEPARTMENT) t

how to select multiple column from the table using group by( based on one column) , having and count in hive query

Requirement :
Using group by A and get records having count > 1
eg:
SELECT count(sk), id, sk
FROM table x
GROUP BY id
HAVING COUNT(sk) > 1
But I am not able to select sk in select statement. Is there any other way to do this. how to use partition on this input and output set attached here?
Something like this, you can do.
select * from (
SELECT count(sk)over(partition by id) as cnt, id, sk
FROM table x) a
where a.cnt >1

Postgres: select the sum of values and then sum this again

I tried a lot but can´t find the right way.
If I select values in Postgres and sum them it looks like this:
SELECT name,sum(size) as total
FROM mytable group by name order by name;
How can I alter this so it also sum all values in total? I think I need a subselect but how?
Try this:
SELECT sum(a.total)
FROM (SELECT sum(size) as total
FROM mytable group by name) a
UPDATE
I'm sorry, I don't read that you want it all in the same query. For this reason the answer of greg it's better. However, other possibility if you have a postgresql version >= 9:
WITH mytableWith (name, sum) as
(SELECT name, sum(size)
FROM mytable
GROUP BY name)
SELECT 'grand total' AS name,
sum(sum) AS sum
FROM mytableWith
UNION ALL
SELECT name, sum
FROM mytableWith
I would use the ROLLUP function on POSTRGESQL:
SELECT name,sum(size) as total
FROM mytable
group by ROLLUP(name )
order by name;
This will give you a grand total of any value that you aggregate and can also be used for aggregating multiple columns.
Hope it helps!
If you want all results with the same SELECT, you could do something like
SELECT
'grand total' AS name,
sum(size) AS sum
FROM
mytable
UNION ALL
SELECT
name,
sum(size) AS sum
FROM
mytable
GROUP BY
name;
Hope it helps…
Well this should help you:
select sum(innerselect.innertotal) as outertotal from
(select sum(size) as innertotal from mytable group by name) as innerselect

Selecting distinct substring values

I have a field that is similar to a MAC address in that the first part is a group ID and the second part is a serial number. My field is alphanumeric and 5 digits in length, and the first 3 are the group ID.
I need a query that gives me all distinct group IDs and the first serial number lexicographically. Here is sample data:
ID
-----
X4MCC
X4MEE
X4MFF
V21DD
8Z6BB
8Z6FF
Desired Output:
ID
-----
X4MCC
V21DD
8Z6BB
I know I can do SELECT DISTINCT SUBSTRING(ID, 1, 3) but I don't know how to get the first one lexicographically.
Another way which seems to have the same cost as the query by gbn:
SELECT MIN(id)
FROM your_table
GROUP BY SUBSTRING(id, 1, 3);
SELECT
ID
FROM
(
SELECT
ID,
ROW_NUMBER() OVER (PARTITION BY SUBSTRING(ID, 1, 3) ORDER BY ID) AS rn
FROM MyTable
) oops
WHERE
rn = 1

Retrieving Representative Records for Unique Values of Single Column

For Postgresql 8.x, I have an answers table containing (id, user_id, question_id, choice) where choice is a string value. I need a query that will return a set of records (all columns returned) for all unique choice values. What I'm looking for is a single representative record for each unique choice. I also want to have an aggregate votes column that is a count() of the number of records matching each unique choice accompanying each record. I want to force choice to lowercase for this comparison to be made (HeLLo and Hello should be considered equal). I can't GROUP BY lower(choice) because I want all columns in the result-set. Grouping by all columns causes all records to return, including all duplicates.
1. Closest I've gotten
select lower(choice), count(choice) as votes from answers where question_id = 21 group by lower(choice) order by votes desc;
The issue with this is it will not return all columns.
lower | votes
-----------------------------------------------+-------
dancing in the moonlight | 8
pumped up kicks | 7
party rock anthem | 6
sexy and i know it | 5
moves like jagger | 4
2. Trying with all columns
select *, count(choice) as votes from answers where question_id = 21 group by lower(choice) order by votes desc;
Because I am not specifying every column from the SELECT in my GROUP BY, this throws an error telling me to do so.
3. Specifying all columns in the GROUP BY
select *, count(choice) as votes from answers where question_id = 21 group by lower(choice), id, user_id, question_id, choice order by votes desc;
This simply dumps the table with votes column as 1 for all records.
How can I get the vote count and unique representative records from 1., but with all columns from the table returned?
Join grouped results back with primary table, then show only one row for each (question,answer) combination.
similar to this:
WITH top5 AS (
select question_id, lower(choice) as choice, count(*) as votes
from answers
where question_id = 21
group by question_id , lower(choice)
order by count(*) desc
limit 5
)
SELECT DISTINCT ON(question_id,choice) *
FROM top5
JOIN answers USING(question_id,lower(choice))
ORDER BY question_id, lower(choice), answers.id;
Here's what I ended up with:
SELECT answers.*, cc.votes as votes FROM answers join (
select max(id) as id, count(id) as votes
from answers
group by trim(lower(choice))
) cc
on answers.id = cc.id ORDER BY votes desc, lower(response) asc