PostgreSQL get results grouped by Name but ordered by modified_date desc for the first element of each group - sql

Suppose that my query:
select modified_date, name from table1 where name in (select name from table2 group by name) as a order by name
return this results:
I need to change my query to get results grouped by Name but ordered by modified_date desc for the first element of each group.
Mean the result should be:

First, your subquery does not need a GROUP BY clause because you are not doing any aggregation.
It could be:
SELECT DISTINCT name FROM table2
but it works fine with a simple:
SELECT name FROM table2
For your sorting problem, if modified_date's data type is DATE you can use MAX() window function:
SELECT modified_date, name
FROM table1
WHERE name IN (SELECT name FROM table2)
ORDER BY MAX(modified_date) OVER (PARTITION BY name) DESC,
name, -- just in case 2 names have the same max modified_date
modified_date DESC;
See the demo.

Related

How to use Array_agg without returning the same values in different Order?

When using Array_agg, it returns the same values in different orders. I tried using distinct in a few places and it didn't work. I tried using an order before and after the array and it would fail or not properly exclude results.
I am trying to find all fields in the field column that share the same time and same ID and put them into an array.
Columns are Fieldname, ID, Time
select b.Field, count(*)
from (select Time, ID, array_agg(fieldname) as Field
from a
group by 1,2
order by 3) b
group by b.field
order by 1 desc
This produces duplicate results
For example I will have:
Field Name Count
Ghost,Mark 1234
Mark,Ghost 1234
I also tried this below where I add a subquery where I first order the fields alphabetically when grouping time and ID but it failed to execute. I think due to array_agg not being the root query?
select a.Field, count(*)
from
(select Time, ID, array_agg(fieldname) as field
from
(select Time, ID, fieldname
from a
group by 1,2
order by 3 desc) a
group by 1,2 ) b
group by 1
order by 2 desc

Filter by number of occurrences in a SQL Table

Given the following table where the Name value might be repeated in multiple rows:
How can we determine how many times a Name value exists in the table and can we filter on names that have a specific number of occurrances.
For instance, how can I filter this table to show only names that appear twice?
You can use group by and having to exhibit names that appear twice in the table:
select name, count(*) cnt
from mytable
group by name
having count(*) = 2
Then if you want the overall count of names that appear twice, you can add another level of aggregation:
select count(*) cnt
from (
select name
from mytable
group by name
having count(*) = 2
) t
It sounds like you're looking for a histogram of the frequency of name counts. Something like this
with counts_cte(name, cnt) as (
select name, count(*)
from mytable
group by name)
select cnt, count(*) num_names
from counts_cte
group by cnt
order by 2 desc;
You need to use a GROUP BY clause to find counts of name repeated as
select name, count(*) AS Repeated
from Your_Table_Name
group by name;
If You want to show only those Which are repeated more than one times. Then use the below query which will show those occurrences which are there more than one times.
select name, count(*) AS Repeated
from Your_Table_Name
group by name having count(*) > 1;

Group by unique customers and then create column for min date

I have a table with customer IDs, transaction_date
Example of table:
ID |transaction_date
PT2073|2015-02-28
PT2073|2019-02-28
PT2013|2015-04-28
PT2013|2017-02-11
PT2013|2017-07-11
GOAL: I want to create another column so that for each unique ID I get the first first transaction date. It should look like:
Example of table:
ID |transaction_date|first_transaction_date
PT2073|2015-02-28 |2015-02-28
PT2073|2019-02-28 |2015-02-28
PT2013|2015-04-28 |2015-04-28
PT2013|2017-02-11 |2015-04-28
PT2013|2017-07-11 |2015-04-28
I created another table where I select the minimum and then group it :
SELECT id, MIN(transaction_date) as first_transaction_date FROM customer_details GROUP BY id
When I checked the table I was not getting the same value in first_transaction_date column for a unique id.
Use min() as a window function:
select t.*, min(t.transaction_date) over (partition by t.id)
from t;
No group by is needed.
Use first_value() window function: It gives out the first value of an ordered group (your groups are the ids that are ordered by the transaction_date):
Click for demo:db<>fiddle
SELECT
*,
first_value(transaction_date) OVER (PARTITION BY id ORDER BY transaction_date)
FROM
mytable
If your Postgres version does not support window functions (prior 8.4, Amazon Redshift):
Click demo:db<>fiddle
SELECT
t1.*,
(SELECT min(transaction_date) FROM mytable t2 WHERE t1.id = t2.id)
FROM
mytable t1

how to select the most recent records

Select id, name , max(modify_time)
from customer
group by id, name
but I get all records.
Order by modify_time desc and use row_number to number the row for id,name combination.Then select each combination with row_number = 1
select id,modify_time,name
from (
select id,modify_time,name,row_number() over(partition by id order by modify_time desc) as r_no
from customer
) a
where a.r_no=1
Ids are unique, which means grouping them by the id, will result in the same table.
My suggestion would be, to order the table by "modify_time" descending and limit the result to 1 (Maybe something like the following):
Select id, name modify_time from customer ORDER BY modify_time DESC limit 1
The reason you are getting the whole table as a result is because you are grouping by id AND name. That means every unique combination of id and name is returned. And since all names per id are different, the whole table is returned.
If you want the last modification per id (or name) you should only group by id (or name respectively).

How to do this query to select N rows with highest numbers ordered by col

Lets say I have a table that has three columns: ID, Name and Users.
I want to select the 3 rows with the highest number of users and I wanted the rows to be ordered by the Name Ascending. How can I Achieve that?
I used
select Name from TABLE where ID IN (select ID from Tablesorder by Users desc limit 3)
But IN/ANY are not supported. Any other ways?
Thanks
When subqueries are allowed, you could use this.
It fetches the 3 records with highest value for column users. These 3 results will be ordered in the outer query.
select Name from
(
select Name
from Tables
order by Users desc
limit 3
) as temp
ORDER BY Name ASC
In Mysql :
SELECT id, name, users
FROM (SELECT id,name,users FROM tablename ORDER BY users DESC LIMIT 3) as a
ORDER BY name;
In Sql server
SELECT id, name, users
FROM (SELECT TOP 3 id,name,users FROM tablename ORDER BY users DESC ) as a
ORDER BY name;
In Oracle
SELECT id, name, users
FROM (SELECT id,name,users FROM tablename ORDER BY users DESC ) as a
WHERE ROWNUM<=3
ORDER BY name;