在3小时的时间内获得超过1000美元的销售记录?

时间:2018-02-13 16:31:36

标签: sql sql-server sql-server-2012

我问,因为我不确定谷歌的用途 - 对我来说似乎显而易见的尝试没有任何用处。

我在具有特定$值的特定日期时间内进入对象数据库。我希望得到所有销售记录组a)(任何,不只是说"在小时"比如凌晨1点到凌晨4点)3小时的时间范围,b)总计> = $ 1000。

表格如下:

Sales
SaleId int primary key
Item varchar
SaleAmount money
SaleDate datetime

即使只是关于我应该谷歌搜索的建议也会受到赞赏大声笑!

编辑:

在尝试交叉应用解决方案后确定 - 它已经关闭但不完全存在。为了说明,请考虑以下示例数据:

-- 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))

从评论中简单改编交叉应用解决方案,逐项:

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

因此实际数据(按项目/时间排序)如下:

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

和交叉申请方法的结果:

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

通过考虑项目1的方法分析可以看出这个问题。从数据中,我们看到第1项的FIRST销售不参与3小时超过1000美元。然而,第二,第三和第四项第1项销售也参与其中。并且他们被正确挑选出来,pkid = 2和3.但是他们的总和是不对的 - 他们的总和包括第1项的第一次出售,它没有参与时间/金额条件。我原本预计pkid 2的saleamount_sum为1135.44,而pkid 3为1456.48(他们报告的金额减去第一次非参与销售)。

希望这是有道理的。我会尝试摆弄交叉应用查询来获取它。任何能够快速了解​​我如何获得我所追求的东西的人,请随时加入。

感谢, -sff

4 个答案:

答案 0 :(得分:1)

以下是使用apply的一种方法:

select t.*, tt.saleamount_sum
from t cross apply
     (select sum(t2.saleamount) as saleamount_sum
      from t t2
      where t2.saledate >= t.saledate and t2.saledate < dateadd(hour, 3, t.saledate)
     ) tt
where tt.saleamount_sum > 1000;

编辑:

如果你想要每个项目(问题中未指定),那么你需要一个条件:

select t.*, tt.saleamount_sum
from t cross apply
     (select sum(t2.saleamount) as saleamount_sum
      from t t2
      where t2.item = t.item and t2.saledate >= t.saledate and t2.saledate < dateadd(hour, 3, t.saledate)
     ) tt
where tt.saleamount_sum > 1000;

答案 1 :(得分:1)

您的查询有一个错误的比较(s.saledate >= s_in.saledate)而不是s_in.saledate >= s.saledate。下面的内部查询查找外部查询的每一行的下一个3小时。

示例数据

DECLARE @Sales TABLE (
    [pkid] [int] IDENTITY(1,1) NOT NULL,
    [item] [int] NULL,
    [amount] [money] NULL,
    [saledate] [datetime] NULL
);

INSERT INTO @Sales VALUES (1, 649.3800, CAST(N'2017-12-31T21:46:19.000' AS DateTime))
INSERT INTO @Sales VALUES (1, 830.6700, CAST(N'2018-01-01T08:38:58.000' AS DateTime))
INSERT INTO @Sales VALUES (1, 321.0400, CAST(N'2018-01-01T09:08:04.000' AS DateTime))
INSERT INTO @Sales VALUES (3, 762.0300, CAST(N'2018-01-01T07:26:30.000' AS DateTime))
INSERT INTO @Sales VALUES (2, 733.5100, CAST(N'2017-12-31T12:04:07.000' AS DateTime))
INSERT INTO @Sales VALUES (3, 854.5700, CAST(N'2018-01-01T08:32:11.000' AS DateTime))
INSERT INTO @Sales VALUES (2, 644.1700, CAST(N'2017-12-31T17:49:59.000' AS DateTime))
INSERT INTO @Sales VALUES (1, 304.7700, CAST(N'2018-01-01T08:01:50.000' AS DateTime))
INSERT INTO @Sales VALUES (2, 415.1200, CAST(N'2017-12-31T20:27:28.000' AS DateTime))
INSERT INTO @Sales VALUES (3, 698.1700, CAST(N'2018-01-01T02:39:28.000' AS DateTime))

INSERT INTO @Sales VALUES (4, 600, CAST(N'2018-01-01T02:39:01.000' AS DateTime))
INSERT INTO @Sales VALUES (4, 600, CAST(N'2018-01-01T02:39:02.000' AS DateTime))
INSERT INTO @Sales VALUES (4, 600, CAST(N'2018-01-01T02:39:03.000' AS DateTime))
INSERT INTO @Sales VALUES (4, 600, CAST(N'2018-01-01T02:39:04.000' AS DateTime))
INSERT INTO @Sales VALUES (4, 600, CAST(N'2018-01-01T02:39:05.000' AS DateTime))
INSERT INTO @Sales VALUES (4, 600, CAST(N'2018-01-01T02:39:06.000' AS DateTime))

<强>查询

select
    s.*
    , s2.saleamount_sum
from
    @Sales AS s
    cross apply
        (
            select sum(s_in.amount) as saleamount_sum
            from @Sales AS s_in
            where 
                s.item = s_in.item
                and s_in.saledate >= s.saledate
                and s_in.saledate < dateadd(hour, 3, s.saledate)
        ) AS s2
where s2.saleamount_sum > 1000
order by s.item, s.saledate
;

<强>结果

+------+------+--------+-------------------------+----------------+
| pkid | item | amount |        saledate         | saleamount_sum |
+------+------+--------+-------------------------+----------------+
|    8 |    1 | 304.77 | 2018-01-01 08:01:50.000 | 1456.48        |
|    2 |    1 | 830.67 | 2018-01-01 08:38:58.000 | 1151.71        |
|    7 |    2 | 644.17 | 2017-12-31 17:49:59.000 | 1059.29        |
|    4 |    3 | 762.03 | 2018-01-01 07:26:30.000 | 1616.60        |
|   11 |    4 | 600.00 | 2018-01-01 02:39:01.000 | 3600.00        |
|   12 |    4 | 600.00 | 2018-01-01 02:39:02.000 | 3000.00        |
|   13 |    4 | 600.00 | 2018-01-01 02:39:03.000 | 2400.00        |
|   14 |    4 | 600.00 | 2018-01-01 02:39:04.000 | 1800.00        |
|   15 |    4 | 600.00 | 2018-01-01 02:39:05.000 | 1200.00        |
+------+------+--------+-------------------------+----------------+

我在示例数据中添加了6行item=4。它们都在3小时内,这6行中有5个子集的总和大于1000.从技术上讲,这个结果是正确的,但你真的想要这种结果吗?

答案 2 :(得分:0)

要在指定的小时间隔内获得所有销售:

SELECT SaleId, sum(SaleAmount) as amount FROM Sales WHERE (HOUR(SaleDate) BETWEEN 1 AND 4) GROUP BY SaleId HAVING amount >=1000;

您可以在WHERE子句中添加其他条件。

答案 3 :(得分:0)

如果你正在寻找0:00-3:00,3:00-6:00这样的时期,你可以按这些时间间隔进行分组。以下查询将小时数舍入为三的倍数,将其与日期和组合在一起:

select  format(dt, 'yyyy-mm-dd') + ' ' + 
            cast(datepart(hour, dt) / 3 * 3 as varchar(2)) as period
,       sum(amount) as total
from    sales
group by
        format(dt, 'yyyy-mm-dd') + ' ' + 
            cast(datepart(hour, dt) / 3 * 3 as varchar(2))
having  sum(amount) > 1000

Working example at regtester.

如果您正在寻找任何3小时的时间段,例如0:33-3:33或12:01-15:01,请参阅Gordon Linoff的回答。