I have this table in MS Access and need to write a query for a report and am struggling. My SQL is largely unused for at least 5 years, and was never really that good, but I thought I could do this without too much trouble...alas.
Product | ProductSubCode | OrderDateTime | Order Amount |
---|---|---|---|
A | 1 | 2021-05-25 11:30 | 5 |
A | 2 | 2021-05-25 12:30 | 50 |
A | 1 | 2021-05-25 13:30 | 500 |
B | 1 | 2021-05-25 09:30 | 400 |
B | 2 | 2021-05-25 10:30 | 40 |
B | 1 | 2021-05-25 11:30 | 4 |
C | 1 | 2021-05-25 13:30 | 30 |
C | 1 | 2021-05-25 14:30 | 300 |
C | 2 | 2021-05-25 15:30 | 3 |
A | 2 | 2021-05-24 11:30 | 5 |
A | 2 | 2021-05-24 12:30 | 50 |
A | 1 | 2021-05-24 13:30 | 500 |
B | 1 | 2021-05-24 09:30 | 400 |
B | 1 | 2021-05-24 10:30 | 40 |
B | 1 | 2021-05-24 11:30 | 4 |
C | 1 | 2021-05-24 13:30 | 30 |
C | 1 | 2021-05-24 14:30 | 300 |
C | 2 | 2021-05-24 15:30 | 3 |
I'm trying to query the above table to display the following results
Product|ProductSubCode|MinYesterday|MaxYesterday|MinTwoDaysAgo|MaxToDaysAgo
ie For each product/sub code, select the min & max order amount for today and yesterday.
What I have so far is as follows;
SELECT distinct Product as masterID,ProductSubCode
(SELECT MIN(Order Amount) FROM TableName WHERE Product = masterID AND DateValue(OrderDateTime) >= DateAdd("d",-1,Date())) AS MinYesterday,
(SELECT MIN(Order Amount) FROM TableName WHERE Product = masterID AND DateValue(OrderDateTime) >= DateAdd("d",-1,Date())) AS MaxYesterday,
(SELECT MIN(Order Amount) FROM TableName WHERE Product = masterID AND DateValue(OrderDateTime) >= DateAdd("d",-2,Date())) AS MinTwoTodayAgo,
(SELECT MIN(Order Amount) FROM TableName WHERE Product = masterID AND DateValue(OrderDateTime) >= DateAdd("d",-2,Date())) AS MaxTwoDaysAgo
FROM TableName
GROUP BY Product, ProductSubCode
I get it, it's definitely wrong but I could really use some help here.
I think you are very close, changed it just a little bit:
It's better to avoid spaces in the column names, so use OrderAmount. If it's not possible to change a column name already, MIN([Order Amount])
will work instead of MIN(Order Amount)
.
You have MIN
in all the rows, whereas it should be MINs and MAXs.
I changed >=
with =
because you need a strict equation there
changed column alias masterID
to table alias t1
SELECT distinct Product, ProductSubCode,
(SELECT MIN(OrderAmount) FROM TableName WHERE Product = t1.Product AND DateValue(OrderDateTime) = DateAdd("d",-1,Date())) AS MinYesterday,
(SELECT MAX(OrderAmount) FROM TableName WHERE Product = t1.Product AND DateValue(OrderDateTime) = DateAdd("d",-1,Date())) AS MaxYesterday,
(SELECT MIN(OrderAmount) FROM TableName WHERE Product = t1.Product AND DateValue(OrderDateTime) = DateAdd("d",-2,Date())) AS MinTwoTodayAgo,
(SELECT MAX(OrderAmount) FROM TableName WHERE Product = t1.Product AND DateValue(OrderDateTime) = DateAdd("d",-2,Date())) AS MaxTwoDaysAgo
FROM TableName t1
GROUP BY Product, ProductSubCode
Try with these small adjustments using alias for the table in the subqueries:
SELECT
Product,
ProductSubCode,
(SELECT MIN(T1.[Order Amount]) FROM TableName AS T1
WHERE T1.Product = TableName.Product AND DateValue(T1.OrderDateTime) = DateAdd("d",-1,Date())) AS MinYesterday,
(SELECT MAX(T2.[Order Amount]) FROM TableName AS T2
WHERE T2.Product = TableName.Product AND DateValue(T2.OrderDateTime) = DateAdd("d",-1,Date())) AS MaxYesterday,
(SELECT MIN(T3.[Order Amount]) FROM TableName AS T3
WHERE T3.Product = TableName.Product AND DateValue(T3.OrderDateTime) = DateAdd("d",-2,Date())) AS MinTwoTodayAgo,
(SELECT MAX(T4.[Order Amount]) FROM TableName AS T4
WHERE T4.Product = TableName.Product AND DateValue(T4.OrderDateTime) = DateAdd("d",-2,Date())) AS MaxTwoDaysAgo
FROM
TableName
GROUP BY
Product,
ProductSubCode
Use conditional aggregation!
SELECT Product as masterID, ProductSubCode,
MIN(IIF(OrderDateTime >= DateAdd("d", -1, Date()) AND OrderDateTime < Date(), [Order Amount], NULL) as MinYesterday,
MAX(IIF(OrderDateTime >= DateAdd("d", -1, Date()) AND OrderDateTime < Date(), [Order Amount], NULL) as MaxYesterday,
MIN(IIF(OrderDateTime >= Date(), [Order Amount], NULL) as MinToday,
MIN(IIF(OrderDateTime >= Date(), [Order Amount], NULL) as MaxToday
FROM TableName
WHERE OrderDateTime >= DateAdd("d", -1, Date())
GROUP BY Product, ProductSubCode;
In addition to being more concise, you should find that this has much, much, much better performance.
Note: This particular formulation assumes that you have no future order dates. It is easy enough to extend the WHERE
clause to remove future order dates if that is an issue.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.