I'm asking because I'm not sure what to google for - attempts that seemed obvious to me returned nothing useful.
I have sales coming into the database of objects at particular datetimes with particular $ values. I want to get all groups of sales records a) within a (any, not just say "on the hour" like 1am-4am) 3 hour time frame, that b) total >= $1000.
The table looks like:
Sales
SaleId int primary key
Item varchar
SaleAmount money
SaleDate datetime
Even just a suggestion on what I should be googling for would be appreciated lol!
EDIT:
Ok after trying the cross apply solution - it's close but not quite there. To illustrate, consider the following sample data:
-- table & data script
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Sales](
[pkid] [int] IDENTITY(1,1) NOT NULL,
[item] [int] NULL,
[amount] [money] NULL,
[saledate] [datetime] NULL,
CONSTRAINT [PK_Sales] PRIMARY KEY CLUSTERED
(
[pkid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
INSERT [dbo].[Sales] VALUES (1, 649.3800, CAST(N'2017-12-31T21:46:19.000' AS DateTime))
INSERT [dbo].[Sales] VALUES (1, 830.6700, CAST(N'2018-01-01T08:38:58.000' AS DateTime))
INSERT [dbo].[Sales] VALUES (1, 321.0400, CAST(N'2018-01-01T09:08:04.000' AS DateTime))
INSERT [dbo].[Sales] VALUES (3, 762.0300, CAST(N'2018-01-01T07:26:30.000' AS DateTime))
INSERT [dbo].[Sales] VALUES (2, 733.5100, CAST(N'2017-12-31T12:04:07.000' AS DateTime))
INSERT [dbo].[Sales] VALUES (3, 854.5700, CAST(N'2018-01-01T08:32:11.000' AS DateTime))
INSERT [dbo].[Sales] VALUES (2, 644.1700, CAST(N'2017-12-31T17:49:59.000' AS DateTime))
INSERT [dbo].[Sales] VALUES (1, 304.7700, CAST(N'2018-01-01T08:01:50.000' AS DateTime))
INSERT [dbo].[Sales] VALUES (2, 415.1200, CAST(N'2017-12-31T20:27:28.000' AS DateTime))
INSERT [dbo].[Sales] VALUES (3, 698.1700, CAST(N'2018-01-01T02:39:28.000' AS DateTime))
A simple adaptation of the cross apply solution from the comments, to go item by item:
select s.*
, s2.saleamount_sum
from Sales s cross apply
(select sum(s_in.amount) as saleamount_sum
from Sales s_in
where s.item = s_in.item
and s.saledate >= s_in.saledate and s_in.saledate < dateadd(hour, 3, s.saledate)
) s2
where s2.saleamount_sum > 1000
order by s.item, s.saledate
So the actual data (sorted by item/time) looks like:
pkid item amount saledate
1 1 649.38 2017-12-31 21:46:19.000
8 1 304.77 2018-01-01 08:01:50.000
2 1 830.67 2018-01-01 08:38:58.000
3 1 321.04 2018-01-01 09:08:04.000
5 2 733.51 2017-12-31 12:04:07.000
7 2 644.17 2017-12-31 17:49:59.000
9 2 415.12 2017-12-31 20:27:28.000
10 3 698.17 2018-01-01 02:39:28.000
4 3 762.03 2018-01-01 07:26:30.000
6 3 854.57 2018-01-01 08:32:11.000
and the result of the cross apply method:
pkid item amount saledate saleamount_sum
2 1 830.67 1/1/18 8:38 AM 1784.82
3 1 321.04 1/1/18 9:08 AM 2105.86
7 2 644.17 12/31/17 5:49 PM 1377.68
9 2 415.12 12/31/17 8:27 PM 1792.8
4 3 762.03 1/1/18 7:26 AM 1460.2
6 3 854.57 1/1/18 8:32 AM 2314.77
The issue can be seen by considering the method's analysis of Item 1. From the data, we see that FIRST sale of item 1 does not participate in a 3-hour-over-$1000. The second, third, and fourth Item 1 sales however do so participate. And they are correctly picked out, pkid = 2 and 3. But their sums aren't right - both of their sums include the very FIRST sale of Item 1, which does not participate in the timespan/amount condition. I would have expected the saleamount_sum for pkid 2 to be 1135.44, and for pkid 3 to be 1456.48 (their reported sums minus the first non-participating sale).
Hopefully that makes sense. I'll try fiddling with the cross apply query to get it. Anyone who can quickly see how to get what I'm after, please feel free to chime in.
thanks, -sff