Aggregate values in columns ONLY there is a difference - sql

Where the values of one column match I want to:
aggregate the data in the other columns where there is a different between the two values
If the values are the same the take the value
Example data
Name Surname Age
Ryan Smith 28
Ryan Smith 29
Sean Johnson 37
Desired result:
Name Surname Age
Ryan Smith 28, 29
Sean Johnson 37
Name ryan appears twice, so want to aggregate the data for the other fields surname and age ONLY where the data is different for the two rows.
Surname is Smith in both rows so no need to aggregate, just want to populate as Smith in one row.
Age is different so want to aggregate the ages for the two rows into one row
Sean Johnson record is unique for all columns so no need to aggregate or amend anything
I have tried string_agg function but this gives the result:
Name Surname Age
Ryan Smith, Smith 28,29
Sean Johnson 37
It aggregates all fields irrespective of whether the data between the two rows is different or not.

You can use:
select name, string_agg(distinct surname, ',') as surname, string_agg(age, ',')
from t
group by name;
This assumes that all names are unique -- that seems like a strong assumption for most datasets.

Related

SQL Result to multiple array

MY SQL returns the following array...
id
staff
province
1
Ben
Ontario
2
Ben
Quebec
3
John
Manitoba
4
John
Saskatchewan
6
Kitty
Alberta
7
Kitty
Nova Scotia
I would like to have the record displayed like this...
staff
province
Ben
Ontario, Quebec
John
Quebec, Manitoba, Saskatchewan
Kitty
Alberta, Nova Scotia
what approach should I use to approach this?
Would be better to post the tables as well for clearer context.
You can use Aggregate functions and Grouping to help doing this. A GROUP BY to group the rows by staff column, then use GROUP_CONCAT() to concatenate province values in one string.
A reference of how you want it to be, unsure what table you are using or if there are any other factors but you can adapt as needed.
SELECT staff, GROUP_CONCAT(province SEPARATOR ', ') as province
FROM table_name
GROUP BY staff;

SQL WHERE column values into capital letters

Let's say I have the following entries in my database:
Id
Name
12
John Doe
13
Mary anne
13
little joe
14
John doe
In my program I have a string variable that is always capitalized, for example:
myCapString = "JOHN DOE"
Is there a way to retrieve the rows in the table by using a WHERE on the name column with the values capitalized and then matching myCapString?
In this case the query would return two entries, one with id=12, and one with id=14
A solution is NOT to change the actual values in the table.
A general solution in Postgres would be to capitalize the Name column and then do a comparison against an all-caps string literal, e.g.
SELECT *
FROM yourTable
WHERE UPPER(Name) = 'JOHN DOE';
If you need to implement this is Knex, you will need to figure out how to uppercase a column. This might require using a raw query.

Grouping values and changing values which do not allow the rest of the row to group

Not sure how to describe this, but I want to group a row of values, where one field has two or more different values and set the value of that (but concatenating or changing the values) to give just one single row.
For example:
I have a simple table (all fields are Strings) of people next to their departments. But some people belong to more than one department.
select department_ind, name
from jobs
;
department_ind name
1 Michael
2 Michael
2 Sarah
3 Dave
2 Sally
4 Sally
I want to group by name, and concatenate the department_ind. So the results show look like:
department_ind name
1,2 Michael
2 Sarah
3 Dave
2,4 Sally
Thanks
Use string_agg()
select string_agg(department_ind::text, ',') as departments,
name
from jobs
group by name;

displaying sql results by a group based on column

I have in my table, say thousands of records. I want to display records together by city. It's a lot more complicated then that, since I need it displayed in alphabetical order as well based on customer name. How do I achieve this? Group BY seems to want to give me a total instead of displaying each of my records. so..
mark zuck some city
john smith cherryville
bill gates some city
jane doe cherryville
should return
bill gates some city
mark zuck some city
jane doe cherryville
john smith cherryville
This is an over-simplification but the idea stands. I appreciate all the help. thank you!
Group by is for aggregations. There is no aggregation in your query. You just want your output to be sorted. In this case, Order By well fits for the purpose.
select * from table1
order by city, customer
In english, get all table1 data sorted by first city, then customer

The best way to get counts of occurrences

I have the following data structure :
FIRSTNAME AGE NICKNAME
Jack 28 Benny
Robert 30 Benny
Pascal 20 Benny
Charles 19 Lence
Anthony 20 Lence
The first column is unique.
The idea is that I have to count how many times the "nickname" is used and I want to output it so that I can I have the following result :
Benny 3
Lence 2
What is the best performant way to do so knowing that I have millions of lines?
Try this:
SELECT NICKNAME,COUNT(NICKNAME)
FROM MyTable
GROUP BY NICKNAME
SELECT NICKNAME, SUM(1) FROM table GROUP BY NICKNAME
agregate count group by firstname, there's no other solution.
by the way, the benny nickname only appears 3 times, not 4.