Count how many employees with the same name exist in the database in PostgreSQL - sql

I have a data table of employees, I want to get how many same name employees in the database. Name information is saved as first_name and last_name. I have tried.
Select count(concat(first_name,'',last_name) as empname, (concat(first_name,'',last_name) as empname from xyz.
getting error.

Your SQL is missing some parentheses (brackets), and to use an aggregation function as well as a non-aggregated column, you must include the non-aggregated column in a GROUP BY
So your SQL should look like this:
Select count(concat(first_name,' ',last_name)) as countempname,
(concat(first_name,' ',last_name)) as empname
from xyz
GROUP BY (concat(first_name,' ',last_name));
Notice also that I added a space. It is a bit odd to include an empty string in the concat. Also as a short form, if you do not want to repeat the concat in the GROUP BY, you can replace it with the column ordinal number (in this case 2) so it becomes:
Select count(concat(first_name,' ',last_name)) as countempname,
(concat(first_name,' ',last_name)) as empname
from xyz
GROUP BY 2;

If you want to count how many times each first/last name tuple appears in the table, you can use aggregation:
select first_name, last_name, count(*) cnt
from xyz
group by first_name, last_name
This gives you one row per first/last name tuple, with the total count. Note that there is not point concatenating the variables; group by can operate of column tuples.
On the other hand, maybe you want the entire employee row, with an additional column that holds the total count of other rows having the same names. If so, you can use a window count instead of aggregation:
select x.*, count(*) over(partiton by first_name, last_name) cnt
from xyz

Related

Return all results from a Query on a single row

I have a query that will return all the results for matching row values between two tables.
The tables are Students and StudentRace. The match in the WHERE statement is STUDENTS.ID = STUDENTRACE.STUDENTID.
I am trying to return the column STUDENTRACE.RACECD where all the matching RACECDs are in a single row in the resulting table. The query does something different, however. IF a STUDENTID has more than 1 RACECD it does not repeat each RACECD in a single row for the STUDENTID. It will return a separate row for each RACECD that matches the STUDENTID.Here is my query:
select
STUDENTS.ID as ID,
STUDENTS.STUDENT_NUMBER as STUDENT_NUMBER,
STUDENTRACE.STUDENTID as STUDENTID,
STUDENTS.FIRST_NAME as FIRST_NAME,
STUDENTS.LAST_NAME as LAST_NAME,
STUDENTRACE.RACECD as RACECD,
STUDENTS.ENROLL_STATUS as ENROLL_STATUS
from
STUDENTRACE STUDENTRACE,
STUDENTS STUDENTS
where
STUDENTS.ID = STUDENTRACE.STUDENTID
and ENROLL_STATUS = 0
Here is the result for a STUDENT ID = 23:
StudentID Racecd
23 B
23 W
This is close but not exactly what I would like to see. I would like the result to be:
StudentID Racecd
23 B,W
or something similar to that. I think I may need the CONCAT function and possibly a nested SELECT statement as well, but I am not sure. I am new to SQL so I am not sure how to move forward.
Like jarlh said I am not sure how you select 7 columns but result in 2?
but Listagg is what I think you are looking for. You can separate it by any delimiter (in this case I put comma). Also any outlying columns will need to appear in the group by
select
STUDENTRACE.STUDENTID as STUDENTID,
listagg(STUDENTRACE.RACECD,',') as RACECD
from STUDENTRACE STUDENTRACE,
STUDENTS STUDENTS
where STUDENTS.ID=STUDENTRACE.STUDENTID
AND ENROLL_STATUS = 0
group by STUDENTRACE.STUDENTID
If you want there two records to become one, you want to group by something, aggregating on something else. In this case you want a single record for each student so you can group by the student_id, and you want all races aggregated so you can use GROUP_CONCAT (in MYSQL, but you can use corresponding aggregation function if in other RDBMS) to concatenate the races. It would be like this:
SELECT s.id, s.name, GROUP_CONCAT(sr.race)
FROM students s join studentrace sr on s.id = sr.student_id
GROUP BY s.id
That is the base to get what you want, then you can add the other fields you are interested in on the select and on the where filters.
SQL Fiddle: http://www.sqlfiddle.com/#!9/ad59d6/1/0
Hope that helps.
If you are using Microsoft SQL Server, you might want to try the following code.
create table Person (
Name nvarchar(450)
)
insert into Person values ('Fabio'), ('Laura')
select stuff((select ',' + Name from Person for xml path('')), 1, 1, '')
The above select statement returns the following string.
Fabio,Laura

In one query, get length of last name, length of first name and group by lengths - three columns

I'm a noob...and working on a homework problem.
Have a members table with last_name, first_name. I want to write one query that aggregates the length of last_name, first_name by string length.
The output would have three columns - name_length, count_of_last_names, count_of_first_names.
Two individual queries:
`SELECT LENGTH(last_name) AS "LnameLen", COUNT(LENGTH(last_name)) AS "CntLnameLen"
FROM members
GROUP BY LENGTH(last_name)
ORDER BY "LnameLen" DESC;
SELECT LENGTH(first_name) AS "FnameLen", COUNT(LENGTH(first_name)) AS "CntFnameLen"
FROM members
GROUP BY LENGTH(first_name)
ORDER BY "FnameLen";`
But I want to write one query that outputs what the above two queries do, so the output would be three columns: Length_of_Name, CntLnameLen, CntFnameLen.
Suggestions? Thanks!
The way I understood the question, something like this might be what you're looking for.
select length(first_name),
length(last_name),
count(*)
from members
group by length(first_name),
length(last_name);

Coalesce of multiple values group by date in postgres

I have a table as shown below:
I need to select columns based on identity_no and also, need to select non zero/non null column values grouped by src_date. so when I query on the identity_no, I want something like:
I need a postgresql statement or even a function is ok. I tried with coalesce. but i can't do group by on src_date. Here src_date is a string and not a date
Use group by and max()
select scr_date,max(upload) as upload, max(download) as download, identity_no, max(email) as email,
max(phone) as phone, min(id) as id
from tablename
group by scr_date,identity_no
You need to group your table by scr_date and other columns need to be aggregated with a method such as min or max. From your output, it seems that the id is the minimum of each group. Other columns don't containt multiple values for each group, therefore min and max would work the same. However you should consider if other columns had multiple values for each group, how would you want them to be aggregated.
select min(id) as id, max(upload) as upload, max(download) as download, max(email) as email, max(phone) as phone, scr_date
from tbl
group by scr_date

How to insert a count column into a sql query

I need the second column of the table retrieved from a query to have a count of the number of rows, so row one would have a 1, row 2 would have a 2 and so on. I am not very proficient with sql so I am sorry if this is a simple task.
A basic example of what I am doing would be is:
SELECT [Name], [I_NEED_ROW_COUNT_HERE],[Age],[Gender]
FROM [customer]
The row count must be the second column and will act as an ID for each row. It must be the second row as the text file it is generating will be sent to the state and they require a specific format.
Thanks for any help.
With your edit, I see that you want a row ID (normally called row number rather than "count") which is best gathered from a unique ID in the database (person_id or some other unique field). If that isn't possible, you can make one for this report with ROW_NUMBER() OVER (ORDER BY EMPLOYEE_ID DESC) AS ID, in your select statement.
select Name, ROW_NUMBER() OVER (ORDER BY Name DESC) AS ID,
Age, Gender
from customer
This function adds a field to the output called ID (see my tips at the bottom to describe aliases). Since this isn't in the database, it needs a method to determine how it will increment. After the over keyword it orders by Name in descending order.
Information on Counting follows (won't be unique by row):
If each customer has multiple entries but the selected fields are the same for that user and you are counting that user's records (summed in one result record for the user) then you would write:
select Name, count(*), Age, Gender
from customer
group by name, age, gender
This will count (see MSDN) all the user's records as grouped by the name, age and gender (if they match, it's a single record).
However, if you are counting all records so that your whole report has the grand total on every line, then you want:
select Name, (select count(*) from customer) as "count", Age, Gender
from customer
TIP: If you're using something like SSMS to write a query, dragging in columns will put brackets around the columns. This is only necessary if you have spaces in column names, but a DBA will tend to avoid that like the plague. Also, if you need a column header to be something specific, you can use the as keyword like in my first example.
W3Schools has a good tutorial on count()
The COUNT(column_name) function returns
the number of values (NULL values will not be counted) of the
specified column:
SELECT COUNT(column_name) FROM table_name;
The COUNT(*) function returns the number of records in a table:
SELECT COUNT(*) FROM table_name;
The COUNT(DISTINCT column_name) function returns the number of
distinct values of the specified column:
SELECT COUNT(DISTINCT column_name) FROM table_name;
COUNT(DISTINCT) works with ORACLE and Microsoft SQL Server, but
not with Microsoft Access.
It's odd to repeat the same number in every row but it sounds like this is what you're asking for. And note that this might not work in your flavor of SQL. MS Access?
SELECT [Name], (select count(*) from [customer]), [Age], [Gender]
FROM [customer]

Select 2 distinct columns in 4GL

Needed for my 4gl program:
Let's say I have a table that holds a phone number and a name. There can be 2 people with the same phone number, or 2 names with 1 phone number.
I need to select just 1 of each phone number in the table.
I did:
SELECT DISTINCT phone_number, last_name FROM table
The results will show 2 records. Even phone number is the same, since the names are different it is no longer unique. How can I get a unique phone number regardless of its last_name? (But I want to get the last name as well. I don't care which one)
DISTINCT, as you've noticed, will return rows that are distinct in their entirety.
It sounds like you're looking for something like group by. Essentially, GROUP BY phone_number will return one row for each phone number. Because you also want to get last_name, you'll need to instruct the database how you want it to be returned. You said you don't care which so you could simply write:
SELECT phone_number, MAX(last_name) as last_name
FROM table
GROUP BY phone_number
Informix also supports a FIRST_VALUE aggregate function although I've only used that in OLAP situations so I don't recall if it will work in this context.
If you don't care which last name, then try this out:
SELECT phone_number,
MAX(last_name) AS last_name
FROM table
GROUP BY phone_number