Finding Most Recent Order for a Particular Item - sql

I'm trying to write a SQL Query for DB2 Version 8 which retrieves the most recent order of a specific part for a list of users. The query receives a parameter which contains a list of customerId numbers and the partId number. For example,
Order Table
OrderID
PartID
CustomerID
OrderTime
I initially wanted to try:
Select * from Order
where
OrderId = (
Select orderId
from Order
where
partId = #requestedPartId# and customerId = #customerId#
Order by orderTime desc
fetch first 1 rows only
);
The problem with the above query is that it only works for a single user and my query needs to include multiple users.
Does anyone have a suggestion about how I could expand the above query to work for multiple users? If I remove my "fetch first 1 rows only," then it will return all rows instead of the most recent. I also tried using Max(OrderTime), but I couldn't find a way to return the OrderId from the sub-select.
Thanks!
Note: DB2 Version 8 does not support the SQL "TOP" function.

Try the following one. I didn't test it. The idea is that you first find all orders for all your specified customers. These will be grouped and you find the biggest order time for each customer (combination of group by and max). This is the foo query, that identifies the records that you need. Than you join it with your order table to retrieve the necessary information for these orders.
select o.*
from order o inner join
(select customerId, max(orderTime)
from order o
where customerId in ( #customerIds#)
and partId = #requestedPartId#
group by customerId) foo
on o.customerId = foo.customerId
and o.orderTime = foo.orderTime
EDIT: The above query gives you the most recent order for each customer you specified under the condition, that there is only one order per customer and orderTime. To get only one order it is slightly different. The following example assumes that the orderTime is unique, meaning there are no two orders at the same time in the database. This is generally be true if orderTime is recorded in milliseconds.
select o.*
from order o inner join
(select customerId, max(orderTime)
from order o
where customerId in ( #customerIds#)
and partId = #requestedPartId#) foo
on o.orderTime = foo.orderTime

Related

SQL Query to pull the last four dates

I am using SQL Server 2012 and trying to pull the 4 most recent order dates in a OrderDate column for certain members. I am not sure how to code for this. Any help will be greatly appreciated.
Order by date in descending order, and limit the number of rows to 4, like this:
select top 4 order_date from orders order by order_date desc
Optimizer will figure out that you have a limit, and optimize your query to avoid sorting the entire table. If order_date column is indexed, query optimizer would use index to get you four dates without going to the table itself.
It should be something similar to this:
select top 4 o.OrderDate
from Members m
inner join Orders o
on m.ID = o.MemberID
where <your certain members criteria>
order by o.OrderDate desc
I'd do something like this (you didn't provide table structure, so this is just pseudo-code).
Create empty table TempOrders to store top orders for each member
Open Cursor to go through all member Ids
For each #MemberId insert into TempOrders select top 4 * from orders where MemberId = #MemberId order by OrderDate desc
your result is in TempOrders table

SQL - fetch records based on a condition of two columns

I need to fetch records where
Order No = ABC
has more than one tracking number in a large table
Can someone help with that?
I'll assume that you're fetching records from Orders and the "large table" is TrackingNumbers. You can group by the OrderNo in a sub-query and refine the sub-query by using a having clause. Then the sub-query will return only OrderNos that are in the table more than once. For example:
select OrderNo
from Orders
where OrderNo in (select OrderNo
from TrackingNumbers
group by OrderNo
having count(*) > 1)
To identify duplicates in a single table (as mentioned in the comments):
select *
from Orders
group by TrackingNumber
having count(*) > 1

select multiple records based on order by

i have a table with a bunch of customer IDs. in a customer table is also these IDs but each id can be on multiple records for the same customer. i want to select the most recently used record which i can get by doing order by <my_field> desc
say i have 100 customer IDs in this table and in the customers table there is 120 records with these IDs (some are duplicates). how can i apply my order by condition to only get the most recent matching records?
dbms is sql server 2000.
table is basically like this:
loc_nbr and cust_nbr are primary keys
a customer shops at location 1. they get assigned loc_nbr = 1 and cust_nbr = 1
then a customer_id of 1.
they shop again but this time at location 2. so they get assigned loc_nbr = 2 and cust_Nbr = 1. then the same customer_id of 1 based on their other attributes like name and address.
because they shopped at location 2 AFTER location 1, it will have a more recent rec_alt_ts value, which is the record i would want to retrieve.
You want to use the ROW_NUMBER() function with a Common Table Expression (CTE).
Here's a basic example. You should be able to use a similar query with your data.
;WITH TheLatest AS
(
SELECT *, ROW_NUMBER() OVER (PARTITION BY group-by-fields ORDER BY sorting-fields) AS ItemCount
FROM TheTable
)
SELECT *
FROM TheLatest
WHERE ItemCount = 1
UPDATE: I just noticed that this was tagged with sql-server-2000. This will only work on SQL Server 2005 and later.
Since you didn't give real table and field names, this is just psuedo code for a solution.
select *
from customer_table t2
inner join location_table t1
on t1.some_key = t2.some_key
where t1.LocationKey = (select top 1 (LocationKey) as LatestLocationKey from location_table where cust_id = t1.cust_id order by some_field)
Use an aggregate function in the query to group by customer IDs:
SELECT cust_Nbr, MAX(rec_alt_ts) AS most_recent_transaction, other_fields
FROM tableName
GROUP BY cust_Nbr, other_fields
ORDER BY cust_Nbr DESC;
This assumes that rec_alt_ts increases every time, thus the max entry for that cust_Nbr would be the most recent entry.
By using time and date we can take out the recent detail for the customer.
use the column from where you take out the date and the time for the customer.
eg:
SQL> select ename , to_date(hiredate,'dd-mm-yyyy hh24:mi:ss') from emp order by to_date(hiredate,'dd-mm-yyyy hh24:mi:ss');

Query to return

I need to write a query which would return results in line with the following.. For three tables, customers, products and order history, I want to find the latest order for each product for each customer. Any help appreciated.
The latest order for each product for each customer - you can achieve this by using a ROW_NUMBER() window function and partitioning your data by those for each criteria.
So try something like this (just guessing table and column names, since you haven't provided anything to go on):
;WITH NewestData AS
(
SELECT
oh.OrderDate,
c.CustomerName,
p.ProductName,
RowNum = ROW_NUMBER() OVER (PARTITION BY oh.CustomerID, oh.ProductID
ORDER BY oh.OrderDate DESC)
FROM
dbo.OrderHistory oh
INNER JOIN
dbo.Customer c ON oh.CustomerID = c.CustomerID
INNER JOIN
dbo.Product p ON oh.ProductID = p.ProductID
)
SELECT
OrderDate, CustomerName, ProductName
FROM
NewestData
WHERE
RowNum = 1
OK, explanation time:
the CTE (Common Table Expression) basically joins the three tables (guessing what the table and column names are, and how they are connected) and selects some of the columns from those tables (you could add more columns, if you need them, of course!)
the RowNum is a consecutive number, starting at 1, for each "partition" of data; the PARTITION BY clause expresses that for each combination of a (CustomerID, ProductID), you want to have a "partition" which gets numbered (1, 2, 3, 4,.....) based on the ORDER BY clause - here, it gets number with 1 for the most recent order for that partition (for that customer+product).
So in the end, all you need to do, is select from that CTE, and select those rows only that have RowNum = 1 - those are the most recent orders for each "partition" of (CustomerID, ProductID) in your order history table.
This works from SQL Server 2005 on and newer versions - it is not supported in 2000 .....

Which customer has placed most orders. SQL query

I'm trying to query my database for my class to find out which customer has placed the most orders. The table I'm searching is a three attribute table that has the customerID, orderID, and the placedDate.
The query I thought would work is:
select cid from placed order by sum(oid);
But I keep getting an error saying cid is "not a single-group group function" the oid is the primary key and is a foreign key that references another table. Is that what the issue is?
If you want to count the number of orders you should do a count instead of a SUM:
SELECT cid,COUNT(*)
FROM placed
GROUP BY cid
ORDER BY COUNT(*) DESC
This will give you the list of customers and their respective number of orders, ordered by the number of orders descendent.
If you want just the customer with most orders, you have to limit the number of records to the first one. For that, you have to tell what DBMS you use, since it varies with the DBMS the way you limit the query to the first one (ex: mysql is LIMIT 1, sql-server is TOP 1):
In Oracle, you can do:
SELECT * FROM (
SELECT cid,COUNT(*)
FROM placed
GROUP BY cid
ORDER BY COUNT(*) DESC
) a
WHERE rownum = 1
In case the there are one or more customers having maximum orders:
select * from orders o, customer c where o.cusId = c.cusId and o.cusId IN (select cusId from orders group by cusId having count(*) = (select count(*) from orders or group by or.cusId order by count(*) desc limit 1));
This solution is for MySQL, as I have used LIMIT. It can be changed as per the DBMS.
I also used = in the second query since LIMIT does not work with IN.