SQL Server 2008 - Select last 3 Booking Ids for each supplier - sql

Id like to return the top three most recent BOOKING_ID, by CREATION_DATE for each active SUPPLIER_ID within a column of bookings.
The active SUPPLIER_ID are gathered with the following query.
select SUPPLIER_ID
into #active
from BookingTable
where BOOKING_ID in (select BOOKING_ID
from BookingTable
where CREATION_DATE > getdate() - 90)
group by SUPPLIER_ID
Is it possible to do this as one query? My current approach is to enter the active SUPPLIER_ID's into a temporary table, and using an outer join to somehow return three records for each supplier.
My expected output is:
SUPPLIER BOOKING
1 12345
1 54656
1 34546
2 54965
2 05650
2 90565

you could use ranking_functions by partitioning through supplier_id
WITH cte
AS (SELECT *,
Row_number()
OVER(
partition BY supplier
ORDER BY creation_date DESC) AS rn
FROM table)
SELECT *
FROM cte
WHERE rn <= 3

I think this should do it ??
select top 3 from table order by CREATION_DATE desc group by SUPPLIER_ID
or like other answer by #Vijaykumar Hadalgi using cte and ROW_NUMBER()/RANK() and PARTITION

Related

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;

Delete Duplicate Rows in SQL

I have a table with unique id but duplicate row information.
I can find the rows with duplicates using this query
SELECT
PersonAliasId, StartDateTime, GroupId, COUNT(*) as Count
FROM
Attendance
GROUP BY
PersonAliasId, StartDateTime, GroupId
HAVING
COUNT(*) > 1
I can manually delete the rows while keeping the 1 I need with this query
Delete
From Attendance
Where Id IN(SELECT
Id
FROM
Attendance
Where PersonAliasId = 15
and StartDateTime = '9/24/2017'
and GroupId = 1429
Order By ModifiedDateTIme Desc
Offset 1 Rows)
I am not versed in SQL enough to figure out how to use the rows in the first query to delete the duplicates leaving behind the most recent. There are over 3481 records returned by the first query to do this one by one manually.
How can I find the duplicate rows like the first query and delete all but the most recent like the second?
You can use a Common Table Expression to delete the duplicates:
WITH Cte AS(
SELECT *,
Rn = ROW_NUMBER() OVER(PARTITION BY PersonAliasId, StartDateTime, GroupId
ORDER BY ModifiedDateTIme DESC)
FROM Attendance
)
DELETE FROM Cte WHERE Rn > 1;
This will keep the most recent record for each PersonAliasId - StartDateTime - GroupId combination.
Use the MAX aggregate function to identify the latest startdatetime for each group/person combination. Then delete records which do not have that latest time.
DELETE a
FROM attendance as a
INNER JOIN (
SELECT
PersonAliasId, MAX(StartDateTime) AS LatestTime, GroupId,
FROM
Attendance
GROUP BY
PersonAliasId, GroupId
HAVING
COUNT(*) > 1
) as b
on a.personaliasid=b.personaliasid and a.groupid=b.groupid and a.startdatetime < b.latesttime
Same as the CTE answer - give Felix the check
delete
from ( SELECT rn = ROW_NUMBER() OVER(PARTITION BY PersonAliasId, StartDateTime, GroupId
ORDER BY ModifiedDateTIme DESC)
FROM Attendance
) tt
where tt.rn > 1

SQL Server Query for distinct rows

How do I query for distinct customers? Here's the table I have..
CustID DATE PRODUCT
=======================
1 Aug-31 Orange
1 Aug-31 Orange
3 Aug-31 Apple
1 Sept-24 Apple
4 Sept-25 Orange
This is what I want.
# of New Customers DATE
========================================
2 Aug-31
1 Sept-25
Thanks!
This is a bit tricky. You want to count the first date a customer appears and then do the aggregation:
select mindate, count(*) as NumNew
from (select CustId, min(Date) as mindate
from table t
group by CustId
) c
group by mindate
You could use a simple common table expression to find the first time a user id is used;
WITH cte AS (
SELECT date, ROW_NUMBER() OVER (PARTITION BY custid ORDER BY date) rn
FROM customers
)
SELECT COUNT(*)[# of New Customers], date FROM cte
WHERE rn=1
GROUP BY date
ORDER BY date
An SQLfiddle to test with.

display max on one columns with multiple columns in output

How can I display maximum OrderId for a CustomerId with many columns?
I have a table with following columns:
CustomerId, OrderId, Status, OrderType, CustomerType
A customer with Same customer id could have many order ids(1,2,3..) I want to be able to display the max Order id with the rest of the customers in a sql view. how can I achieve this?
Sample Data:
CustomerId OrderId OrderType
145042 1 A
110204 1 C
145042 2 D
162438 1 B
110204 2 B
103603 1 C
115559 1 D
115559 2 A
110204 3 A
I'd use a common table expression and ROW_NUMBER:
;With Ordered as (
select *,
ROW_NUMBER() OVER (PARTITION BY CustomerID
ORDER BY OrderId desc) as rn
from [Unnamed table from the question]
)
select * from Ordered where rn = 1
select * from table_name
where orderid in
(select max(orderid) from table_name group by customerid)
One way to do this is with not exists:
select t.*
from table t
where not exists (select 1
from table t2
where t2.CustomerId = t.CustomerId and
t2.OrderId > t.OrderId
);
This is saying: "get me all rows from t where there is no higher order id for the customer."

Select first purchase for each customer

We are trying to select the first purchase for each customer in a table similar to this:
transaction_no customer_id operator_id purchase_date
20503 1 5 2012-08-24
20504 1 7 2013-10-15
20505 2 5 2013-09-05
20506 3 7 2010-09-06
20507 3 7 2012-07-30
The expected result from the query that we are trying to achieve is:
transaction_no customer_id operator_id first_occurence
20503 1 5 2012-08-24
20505 2 5 2013-09-05
20506 3 7 2010-09-06
The closest we've got is the following query:
SELECT customer_id, MIN(purchase_date) As first_occurence
FROM Sales_Transactions_Header
GROUP BY customer_id;
With the following result:
customer_id first_occurence
1 2012-08-24
2 2013-09-05
3 2010-09-06
But when we select the rest of the needed fields we obviously have to add them to the GROUP BY clause which will make the result from MIN different. We have also tried to joining it on itself, but haven't made any progress.
How do we get the rest of the correlated values without making the aggregate function confused?
You can simply treat the query you have come up with as an inner query. This will work on older version of SQL Server as well (you didn't specify version of SQL Server).
SELECT H.transaction_no, H.customer_id, H.operator_id, H.purchase_date
FROM Sales_Transactions_Header H
INNER JOIN
(SELECT customer_id, MIN(purchase_date) As first_occurence
FROM Sales_Transactions_Header
GROUP BY customer_id) X
ON H.customer_id = X.customer_id AND H.purchase_date = X.first_occurence
You can use the ROW_NUMBER function to help you with that.
This is how to do it for your case.
WITH Occurences AS
(
SELECT
*,
ROW_NUMBER () OVER (PARTITION BY customer_id order by purchase_date ) AS "Occurence"
FROM Sales_Transactions_Header
)
SELECT
transaction_no,
customer_id,
operator_id,
purchase_date
FROM Occurences
WHERE Occurence = 1
Sounds like a job for a CTE!
Clicky!
The CTE will allow you to get the earliest purchase date for each customer. Then you join that back to your original table on customer_id and the date, getting the rest of the information for that transaction.
Like so:
with first_date as(
select customer_id,
min(purchase_date) as first_purchase
from
table1
group by
customer_id
)
select
t1.transaction_no,
t1.customer_id,
t1.operator_id,
t1.purchase_date
from
table1 t1
inner join first_date
on
purchase_date = first_purchase
and t1.customer_id = first_date.customer_id
Below query will also provide the solution
select * from customer_sale_details
where purchase_date in (select min(purchase_date)
from customer_sale_details c1 group by c1.customer_id);