Postgres combine 2 columns and use group by - sql

I have pat_first_name and pat_last_name columns in my psql database col. Id like to pick out most common names. I can do first names using
SELECT pat_first_name,count(pat_first_name)
from patients
GROUP BY pat_first_name
ORDER BY count DESC;`
However, when I try combine it fails
SELECT pat_first_name,pat_last_name,count((pat_first_name || ' ' || pat_last_name))
from patients
GROUP BY (pat_first_name || ' ' || pat_last_name)
ORDER BY count DESC;
column "patients.pat_first_name" must appear in the GROUP BY clause or be used in an aggregate function
where am I going wrong?

You can just do:
SELECT pat_first_name,pat_last_name,COUNT(*)
FROM patients
GROUP BY pat_first_name,pat_last_name
ORDER BY COUNT(*) DESC;
Or, if you really want the first_name and last_name concatenated in the result:
SELECT pat_first_name || ' ' || pat_last_name,COUNT(*)
FROM patients
GROUP BY pat_first_name || ' ' || pat_last_name
ORDER BY COUNT(*) DESC;
Either way, you gotta have the same "non-count" columns in the SELECT as in the GROUP BY.

Related

Oracle SQL query CONCAT, GROUP BY

I have this table
I wanted to sort by POS ASC and also aggregate the two columns X,Y so that my ID becomes Unique. So the result should be like this.
I tried for many hours and I could aggregate the column X,Y. But when I'm doing a GROUP BY ID and then WMCONCAT(X,Y) I couldn't sort it by the POS col....
Any help maybe..? Thanks.
Instead of using WM_CONCAT, try using the LISTAGG aggregate function: it allows you to specify an ordering of your choice:
SELECT ID,
LISTAGG('(' || X || ', ' || Y || ')', ', ') WITHIN GROUP (ORDER BY POS) AS XY
FROM tab
GROUP BY ID
Check the demo here.

SQL Group By subquery in postgresql

I want to group by the foolowing table but I also need to group the column ID as depitected on the image.
SELECT SUM(ml),sku,name FROM consumos
GROUP BY sku,name
ORDER BY name
Any ideas?
Best regards
Looks like you want a JSON array. This can be done using jsonb_agg():
select name, sku, ml, jsonb_agg(id)
from the_table
group by name, sku, ml;
In standard SQL, this would look like:
select name, sku, ml,
'[' || listagg(id, ',') within group (order by id) || ']' as ids
from t
group by name, sku, ml
order by name, count(*);
However, not all databases support that standard operator || for string concatenation. And not all databases call their string aggregation operator listagg(). So you might need to tweak the query for your database.
EDIT:
In Postgres, this would be:
select name, sku, ml,
'[' || string_agg(id, ',' order by id) || ']' as ids
from t
group by name, sku, ml
order by name, count(*);

SQL (Redshift) concat multiple rows under one ID

I have 3 columns in my table
Products (product_id, product_detail_name, product_detail_value)
For each product, I want all its details to be in a single cell, i.e in the below format:
product_id, concatenated_values
Use string aggregation function listagg():
select product_id, listagg(product_detail_value) product_details
from mytable
group by product_id
Or if you want to see the results as comma-separated 'name: value' pairs, then:
select
product_id,
listagg(product_detail_name || ': ' || product_detail_value) product_details
from mytable
group by product_id
listagg() also supports an order by clause (with the within group syntax), that is described in the documentation.
You can also use the second section of LISTAGG to define the delimiter.
Select product_id,
Listagg(product_detail_name || ':' || product_detail_value, ' ,') p_details
from mytable
Group By product_id;

How to use LISTAGG and WHERE together

So I am trying to use a LISTAGG function while using a WHERE statement.
What I want to do is search by the WHERE statement and the LISTAGG returns a list with in relations to other columns.
In other words, when I use the WHERE statement with LISTAGG, I only get the value that I'm searching for. The other values associated with the other columns don't show up.
My script is kind of like this:
WITH TEST AS
(
SELECT DISTINCT
LOCATION,
ID,
LISTAGG (TOMATOCOUNT, ', ')
WITHIN GROUP (ORDER BY TOMATOCOUNT)
OVER (PARTITION BY LOCATION, ID) TOMATOTYPES,
FROM TOMATOLAND
)
SELECT
*
FROM TEST
WHERE (:TOMATOTYPE = TOMATO
OR :TOMATOTYPE IS NULL)
Filter on the result of LISTAGG strikes me as a bit backwords. Generally, if you're going to aggregate several items into a list, you're doing it at the last minute, for display purposes. ideally you would filter prior to the aggregation.
The following will return one row for each location/ID that contains the specified tomatotype.
SELECT DISTINCT
location,
id,
LISTAGG (tomatotype, ', ')
WITHIN GROUP (ORDER BY tomatocount)
OVER (PARTITION BY location, id)
tomatotypes
FROM tomatoland
WHERE (location, id) IN (SELECT location, id
FROM tomatoland
WHERE :tomatotype = tomatotype)
OR :tomatotype IS NULL
I think you want something like this:
WITH TEST AS (
SELECT LOCATION, ID,
LISTAGG(TOMATOTYPE, ', ') WITHIN GROUP (ORDER BY TOMATOCOUNT) OVER (PARTITION BY LOCATION, ID) as TOMATOTYPES
FROM TOMATOLAND
)
SELECT *
FROM TEST
WHERE ', ' || :TOMATOTYPE || ', ' LIKE '%,' || TOMATOTYPES || ', %' OR
:TOMATOTYPE IS NULL

ORA - 02287 sequence number not allowed here

I have a table name test which has three columns id, m_id and s_m_id
I am executing below query
select id,test.nextval listagg(m_id || ',' || s_m_id, ';') within group (order by m_id) as merge_ids
from test t group by id
than I am getting error ORA - 02287 sequence number not allowed here.
You're trying to do too many things in one go. Create a subquery for the grouping and add the sequence numbers later:
select id, test.nextval, merge_ids
from (
select id, listagg(m_id || ',' || s_m_id, ';') within group (order by m_id) as merge_ids
from test t
group by id
)