Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Tsql 满足SQL Server 2008第一天标准_Tsql_Sql Server 2008 - Fatal编程技术网

Tsql 满足SQL Server 2008第一天标准

Tsql 满足SQL Server 2008第一天标准,tsql,sql-server-2008,Tsql,Sql Server 2008,我有一个数据表,将有数百万条记录,但我会在这里简化,看起来像这样 ID APPROVAL_DT DAY_DT TRANS_COUNT SALE_AMOUNT 1 2010-04-22 2010-04-27 2 260 1 2010-04-22 2010-04-28 1 40 2 2010-03-28 2010-04-02 1

我有一个数据表,将有数百万条记录,但我会在这里简化,看起来像这样

ID   APPROVAL_DT       DAY_DT        TRANS_COUNT     SALE_AMOUNT
1    2010-04-22        2010-04-27    2               260
1    2010-04-22        2010-04-28    1               40
2    2010-03-28        2010-04-02    1               5
2    2010-03-28        2010-04-03    5               10
2    2010-03-28        2010-04-04    1               20
3    2010-04-25        2010-05-01    6               10
3    2010-04-25        2010-05-02    4               10
4    2010-06-01        2010-06-07    1               5
我需要计算出每个ID的日期,其中所有前一天和当前日期的交易金额之和>=10,或者所有前一天和当前日期的销售金额之和>=25

因此,应用于上表的查询结果将是

ID   APPROVAL_DT  ACTIVATED_DT
1    2010-04-22   2010-04-27
2    2010-03-28   2010-04-04
3    2010-04-25   2010-05-02
4    2010-06-01   NULL

有什么想法吗?

每个id有多少条记录

伊齐克·本·甘(Itzik Ben Gan)比较了处理SQL Server 2008中运行总数的各种方法

他在测试中得出的结论是,直到每个分区有15条记录为止,这是最好的。在这一点上,方法变得更好了。三角形连接继续优于bog标准TSQL游标,直到分区大小达到500


显然,您的里程数可能会有所不同,但我认为这些都是有用的数字。

我想您的意思是,您希望在ID中找到前一天的总里程数>=10或销售额>=25的第一天里程数。你称这一天为“激活日”。您的描述与此完全不同,因为它没有指定您只需要第一天,它要求计算所有前几天的总和,而您的示例结果显示截至当天的总和

我同意Martin的观点,运行总计是表现最好的,因为它可以在表格的一次扫描中产生结果

没有运行总计的结果必须计算前几天每天的总计,然后为每个ID选择第一个:

with cte1 as (
select
  t.id,
  t.approval_dt,
  t.day_dt as activated_dt
from Table t
cross apply (
  select sum(trans_count) as sum_tc,
     sum(sale_amount) as sum_sa,
     max(day_dt) as max_day_dt
  from table c
  where c.id = t.id
  and c.day_dt <= t.day_dt) as p
where p.sum_tc >= 10
or p.sum_sa >=25)
, cte2 as (
  select id
   , approval_dt
   , activated_dt
   , row_number() over (partition by id order by activated_dt) as rn
  from cte1)
select *
from cte2
where rn = 1;

好的。振作起来。我使用了一点作弊的方法,使用了running-total-UPDATE方法。这其中有一些怪癖,所以在生产代码中加入它会让你感到厌倦。其中最大的问题是如何遍历表。可能应该在APPROVAL_DAY列上放置一个聚集索引,以确保不拆分日期。不管怎么说,我来了

CREATE TABLE #test
(
    ID   int,
    APPROVAL_DT   date,    
    DAY_DT        date,
    TRANS_COUNT     int,
    SALE_AMOUNT int,
    DailyTransCount int,
    DailySalesTotal int
)

INSERT INTO #test
SELECT 1,'2010-04-22','2010-04-27',2,260,0,0 UNION ALL
SELECT 1,'2010-04-22','2010-04-28', 1,40, 0,0 UNION ALL
SELECT 2,'2010-03-28','2010-04-02', 1,5, 0,0 UNION ALL
SELECT 2,'2010-03-28','2010-04-03', 5,10, 0,0 UNION ALL
SELECT 2,'2010-03-28','2010-04-04', 1,20, 0,0 UNION ALL
SELECT 3,'2010-04-25','2010-05-01', 6,10, 0,0 UNION ALL
SELECT 3,'2010-04-25','2010-05-02', 4,10, 0,0 UNION ALL
SELECT 4,'2010-06-01','2010-06-07', 1,5, 0,0

DECLARE @PreviousDay date; SET @PreviousDay = '29991231'
DECLARE @DailyTransCount int; SET @DailyTransCount = 0
DECLARE @DailySalesTotal int; SET @DailySalesTotal = 0
DECLARE @Group int; SET @Group = 0

UPDATE #test
    SET DailyTransCount = 0,
        DailySalesTotal = 0

UPDATE #test
    SET @DailyTransCount = DailyTransCount = CASE WHEN APPROVAL_DT = @PreviousDay THEN @DailyTransCount + Trans_Count ELSE Trans_Count END,
        @DailySalesTotal = DailySalesTotal = CASE WHEN APPROVAL_DT = @PreviousDay THEN @DailySalesTotal + SALE_AMOUNT ELSE SALE_AMOUNT END,
        @PreviousDay = APPROVAL_DT

SELECT Y.ID, X.APPROVAL_DT, X.DAY_DT FROM 
    (SELECT DISTINCT(ID) FROM #test T) Y
    LEFT JOIN ( SELECT ID, APPROVAL_DT, MIN(DAY_DT) AS DAY_DT FROM #test
                WHERE DailyTransCount >= 10 OR DailySalesTotal >= 25
                GROUP BY ID, APPROVAL_DT ) X ON X.ID = Y.ID

我应该解释几件事:我在表的末尾又创建了两列。您需要将其放入临时表或永久表中,以将总数推送到。在我把所有的总数都推到列中之后,只需选择就可以检索结果。关于这项技术有更多的信息。请注意,此解决方案速度快,但有点不安全。

使用SSIS 2008的答案也是可以接受的!从您的描述中,我无法理解为什么第1行是ID 1的正确激活行,b ID 2如何满足您使用的前一个标准中的任何一个,这将倾向于表明当前行不包括在比较中,但我不确定这是否正确,因为第1行是ID 1的正确激活行,因为销售金额>=25。ID 2符合2010年4月4日的销售金额标准。ID 3符合2010年5月2日的trans_计数标准。我想它应该是所有前一行+当前行。我将更新问题。每个ID的平均记录为41,最大值为232,最小值为1,请尝试。我有大约60万条记录要测试。看起来我已经被保存了一份工作:-它确实很快,但它依赖于完全未记录的行为。另请参见此处的规则部分。+1,因为该技巧仍然很好地掌握,并在您的工具箱中。我们现在需要担心3000年虫子吗;但是你没有遵守规则部分,这就是我指出的原因!没有聚集索引,没有'OPTION MAXDOP 1`@Martin-谢谢你把这篇文章放在这里,让其他人可以阅读规则@雷姆斯-如果我们能活到2999年,我们都会有工作保障:在我的600K记录测试中,这只花了13秒。它每周运行一次,所以性能没什么大不了的,13秒当然可以接受。如果你按ID对表进行聚类索引,我打赌它会运行得更快。当然,您不应该为每周只使用一次的标准对其进行集群。尽管如此,我猜想其他查询类似于在日期范围内查找订单ID,所以我会考虑和评估像这样的表的聚类。您当前的聚集索引键是什么?当前没有任何索引标记?因为我刚刚开始这个过程。我将研究您提到的聚集索引。sys.indexes:。因此,“索引”在词源上可能不准确,但在技术上是正确的。如果您的表目前是一个堆,那么像我建议的那样的聚集键可能是一个好主意,不仅对于这个查询。我建议您先看一下设计索引一章