Group by clause with min - sql

I am having the following table
I used following query and i got error message. I can identify why the error is but how can i solve it
select min(id),customer_id,created_at from thunderbolt_orders
group by customer_id
I need the minimum id's customer_id and created_at how can i achieve it.

select distinct on (customer_id)
customer_id, id, created_at
from thunderbolt_orders
order by customer_id, id

with cte as (
select
*, row_number() over(partition by customer_id order by id) as row_num
from Table1
)
select *
from cte
where row_num = 1

SELECT id,customer_id,created_at
FROM thunderbolt_orders
WHERE id IN
(SELECT MIN(id) FROM thunderbolt_orders GROUP BY customer_id);

Depending on whether or not you just want the minimum ID or whether you want the minimum ID for each customer these are the solutions.
Minimum ID:
select top 1 id,customer_id,created_at from thunderbolt_orders order by id asc
Minimum ID for each customer:
with cte as (
select min(id) as id
from thunderbolt_orders
group by customer_id
)
select *
from cte c
inner join thunderbolt_orders t on t.id = c.id

Related

Group by column and get max and min id on sql

I got a table with theses Column :
ID_REAL,DATE_REAL,NAME_REAL
I want to make a query to get result like this with a group by on the name
NAME | MAX(DATE_REAL) | ID_REAL of the MAX(DATE_REAL) | MIN(DATE_REAL) | ID_REAL of the MIN(DATE_REAL)
I dont know how to make it for the moment I have
select NAME_REAL,max(DATE_REAL),ID_REAL from MYREALTABLE group by NAME_REAL,ID_REAL
select NAME_REAL,min(DATE_REAL),ID_REAL from MYREALTABLE group by NAME_REAL,ID_REAL
But is not whats I need, and also I need only 1 query
Thanks you
I think the following should work by finding the records which have the minimum and maximum dates per name and joining those two queries.
select
mn.NAME_REAL,
MIN_DATE_REAL,
ID_REAL_OF_MIN_DATE_REAL,
MAX_DATE_REAL,
ID_REAL_OF_MAXDATE_REAL
from
(
select NAME_REAL,
DATE_REAL as MIN_DATE_REAL,
ID_REAL as ID_REAL_OF_MIN_DATE_REAL,
from (
select
NAME_REAL,
ID_REAL,
DATE_REAL,
row_number() over (partition by NAME_REAL order by DATE_REAL asc) as date_order_asc
from MYREALTABLE
)
where date_order_asc = 1
) mn
inner join
(
select NAME_REAL,
DATE_REAL as MAX_DATE_REAL,
ID_REAL as ID_REAL_OF_MAX_DATE_REAL,
from (
select
NAME_REAL,
ID_REAL,
DATE_REAL,
row_number() over (partition by NAME_REAL order by DATE_REAL desc) as date_order_desc
from MYREALTABLE
)
where date_order_desc = 1
) mx
on mn.NAME_REAL = mx.NAME_REAL
You can join the two results into a single query result as follows
select o.NAME_REAL,o.max,o.id_real,t.min,o.id_real from (
select NAME_REAL,max(DATE_REAL) as max,ID_REAL, from MYREALTABLE group by NAME_REAL,ID_REAL)
as o inner join
(select NAME_REAL,min(DATE_REAL),ID_REAL from MYREALTABLE group by NAME_REAL,ID_REAL
) as t on o.NAME_REAL=t.NAME_REAL
Try the below -
select NAME_REAL,ID_REAL,max(DATE_REAL) as max_date, min(DATE_REAL) as min_date
from MYREALTABLE
group by NAME_REAL,ID_REAL

Select most recent status for each ID and department code

I have the following table:
I want to get the most recent status for each dept_code that a CL_ID has. So the desired output would be this:
I have tried the following but this give me just the most recent status for each client and not each of their dept_codes.
SELECT *
FROM [CIMSHR6_MERGED].[dbo].[C3CLSTAT] C
INNER JOIN
(SELECT CLIENT_NUMBER, MAX(STATUS_DATE) AS SDATE
FROM [CIMSHR6_MERGED].[dbo].[C3CLSTAT]
GROUP BY CLIENT_NUMBER) X
ON X.CLIENT_NUMBER = C.CLIENT_NUMBER
AND X.SDATE = C.STATUS_DATE
ORDER BY C.CLIENT_NUMBER
Any help would be much appreciated. Thanks.
A convenient method that works in SQL Server is:
select top (1) cl.*
from [CIMSHR6_MERGED].[dbo].[C3CLSTAT] cl
order by row_number() over (partition by cl_id, dept_code order by status_date desc);
A method that is efficient with the right indexes in almost any database is:
select cl.*
from [CIMSHR6_MERGED].[dbo].[C3CLSTAT] cl
where cl.status_date = (select max(cl2.status_date)
from [CIMSHR6_MERGED].[dbo].[C3CLSTAT] cl2
where cl2.cl_id = cl.cl_id and cl2.dept_code = cl.dept_code
);
The right index is on (cl_id, dept_code, status_date).
I would also use ROW_NUMBER, but with a subquery:
SELECT CL_ID, Status_date, Status, Dept_code
FROM
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY CL_ID, Dept_code ORDER BY Status_date DESC) rn
FROM CIMSHR6_MERGED].[dbo].[C3CLSTAT]
) t
WHERE rn = 1;
1) Firstly group everything on Dept_Code,CL_ID and assign rank for each row with in the group in descending order.
2) Select all the rows with rnk=1 which would display your desired result.
SELECT Z.CL_ID,
Z.Status_Date,
Z.Status,
Z.Dept_Code
FROM
(
SELECT *,
RANK() OVER( PARTITION BY Dept_Code,CL_ID, ORDER BY Status_Date DESC ) AS rnk
FROM [CIMSHR6_MERGED].[dbo].[C3CLSTAT]
) Z
WHERE Z.rnk = 1;
This would work for almost all databases
select * from c3clstat c
where exists
(select 1 from c3clstat c1
where c1.cl_id=c.cl_id
and c1.dept_code=c.dept_code
group by cl_id,dept_code
having c.status_date=max(c1.status_date)
)

Sql query to fetch second latest entry from a table

I have a table with below mentioned columns. I want to fetch the previous status of customer. Once customer id can have multiple entries
Customer_id status start_date end_date Active
1 Member 01-JAN-18 04-FEB-18 N
1 Explorist 05-FEB-18 30-APR-18 N
1 Globalist 01-MAY-18 31-DEC-99 Y
Desired output
Customer _id Previous_status end_date
1 Explorist 30-APR-18
Please try below query using QUALIFY keyword and ROW_NUMBER():
SELECT a.* from table a
QUALIFY ROW_NUMBER OVER(PARTITION BY customer_id order by start_date desc) = 2
Below query should work.
SELECT * from (
SELECT a.*,
ROW_NUMBER() over (partition by customer_id order by start_date desc) rn
from table a )
where rn =2
You can use below query and I guess that is very simple and that worked for me,
select * from customer order by end_date desc limit 1,1
Consider this question: Select Nth Row From A Table In Oracle
In your case, that would be:
select * from (select a.*, rownum rnum from (select * from <your table name>
order by <start_date or end_date> desc) a where rownum <= 2) where rnum >= 2;
If you are using Oracle DataBase then try below query using ROW_NUMBER() function:Let's consider the table name is customer
SELECT TEMP.CUSTOMER_ID
,TEMP.STATUS
,TEMP.START_DATE
,TEMP.END_DATE
,TEMP.ACTIVE
FROM(
SELECT ROW_NUMBER() OVER (PARTITION BY CUSTOMER_ID ORDER BY CUSTOMER_ID ASC,START_DATE DESC) AS "ROW_NUM"
,CUSTOMER_ID
,STATUS
,START_DATE
,END_DATE
,ACTIVE
FROM CUSTOMER) TEMP
WHERE TEMP."ROW_NUM" = 2;

Query to pull second smallest id

CUSTOMER(ID,CASE_ID,NAME,STATE)
1,100,Alex,NY
2,100,Alex,VA
3,100,Alex,CT
4,100,Tom,PA
5,102,Peter,MO
6,103,Dave,TN
.
.
.
How to write a query to pull 2nd smallest (min) id (if present) for every group of case_id
Please try:
SELECT
ID,
CASE_ID
FROM
(
SELECT
*,
ROW_NUMBER() OVER(PARTITION BY CASE_ID ORDER BY ID) Rn
FROM CUSTOMER
)x
WHERE Rn=2
You can use a windowing function:
with cte as (
select ID, CASE_ID, ROW_NUMBER() over (partition by CASE_ID order by ID) rn
from CUSTOMER
)
select ID, CASE_ID
from cte
where rn = 2
Or you can use an exists clause to remove the first row (i.e. get the minimum value where there is a row with a lower value):
select MIN(ID) ID, CASE_ID
from CUSTOMER c
where exists (select 1 from CUSTOMER c2 where c2.ID < c.ID and c2.CASE_ID = c.CASE_ID)
group by CASE_ID
Or, written another way:
select MIN(ID) ID, CASE_ID
from CUSTOMER c
where c.ID > (select MIN(ID) from CUSTOMER c2 where c2.CASE_ID = c.CASE_ID)
group by CASE_ID

How to reverse the table that comes from SQL query which already includes ORDER BY

Here is my query:
SELECT TOP 8 id, rssi1, date
FROM history
WHERE (siteName = 'CCL03412')
ORDER BY id DESC
This the result:
How can I reverse this table based on date (Column2) by using SQL?
You can use the first query to get the matching ids, and use them as part of an IN clause:
SELECT id, rssi1, date
FROM history
WHERE id IN
(
SELECT TOP 8 id
FROM history
WHERE (siteName = 'CCL03412')
ORDER BY id DESC
)
ORDER BY date ASC
You could simply use a sub-query. If you apply a TOP clause the nested ORDER BY is allowed:
SELECT X.* FROM(
SELECT TOP 8 id, Column1, Column2
FROM dbo.History
WHERE (siteName = 'CCL03412')
ORDER BY id DESC) X
ORDER BY Column2
Demo
The SELECT query of a subquery is always enclosed in parentheses. It
cannot include a COMPUTE or FOR BROWSE clause, and may only include an
ORDER BY clause when a TOP clause is also specified.
Subquery Fundamentals
try the below :
select * from (SELECT TOP 8 id, rssi1, date
FROM history
WHERE (siteName = 'CCL03412')
ORDER BY id DESC ) aa order by aa.date DESC
didn't run it, but i think it should go well
WITH cte AS
(
SELECT id, rssi1, date, RANK() OVER (ORDER BY ID DESC) AS Rank
FROM history
WHERE (siteName = 'CCL03412')
)
SELECT id, rssi1, date
FROM cte
WHERE Rank <= 8
ORDER BY Date DESC
I have not run this but i think it will work. Execute and let me know if you face error
select id, rssi1, date from (SELECT TOP 8 id, rssi1, date
FROM history
WHERE (siteName = 'CCL03412')
ORDER BY id DESC) order by date ;