在 SQL 中计算运行值的最有效方法

发布于 2024-12-11 18:27:51 字数 773 浏览 0 评论 0原文

可能的重复:
计算 SqlServer 中的运行总计

考虑此数据

     Day | OrderCount
       1       3
       2       2 
       3       11
       4       3
       5       6

我如何获得此累积使用 T-SQL 查询的 OrderCount(running value) 结果集

      Day | OrderCount | OrderCountRunningValue
       1        3            3
       2        2            5
       3        11           16
       4        3            19
       5        6            25

我可以通过在实际查询中循环(使用 #table)或在我的 C# 代码隐藏中轻松地做到这一点,但它太慢了(考虑到我也得到了每个订单)天)当我处理数千条记录时,所以我正在寻找更好/更有效的方法,希望没有循环,比如递归 CTE 或其他东西。

任何想法将不胜感激。 TIA

Possible Duplicate:
Calculate a Running Total in SqlServer

Consider this data

     Day | OrderCount
       1       3
       2       2 
       3       11
       4       3
       5       6

How can i get this accumulation of OrderCount(running value) resultset using T-SQL query

      Day | OrderCount | OrderCountRunningValue
       1        3            3
       2        2            5
       3        11           16
       4        3            19
       5        6            25

I Can easily do this with looping in the actual query (using #table) or in my C# codebehind but its so slow (Considering that i also get the orders per day) when im processing thousand of records so i'm looking for better / more efficient approach hopefully without loops something like recursing CTE or something else.

Any idea would be greatly appreciated. TIA

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

情释 2024-12-18 18:27:51

由于您似乎需要在客户端中使用这些结果而不是在另一个 SQL 查询中使用,因此您最好不要在 SQL 中执行此操作。

(我的评论中的链接问题显示了 SQL 中的“最佳”选项,如果确实有必要的话。)

建议将 Day 和 OrderCount 值作为一个结果集(SELECT day, orderCount FROM yourTable ORDER BY day),然后在 C# 中计算运行总计。

您的 C# 代码将能够高效地迭代数据集,并且几乎肯定会优于 SQL 方法。这样做的目的是将一些负载从 SQL Server 转移到 Web 服务器,但总体上(并且显着)节省了资源。

As you seem to need these results in the client rather than for use within another SQL query, you are probably better off Not doing this in SQL.

(The linked question in my comment shows 'the best' option within SQL, if that is infact necessary.)

What may be recommended is to pull the Day and OrderCount values as one result set (SELECT day, orderCount FROM yourTable ORDER BY day) and then calculate the running total in your C#.

Your C# code will be able to iterate through the dataset efficiently, and will almost certainly outperform the SQL approaches. What this does do, is to transfer some load from the SQL Server to the web-server, but at an overall (and significant) resource saving.

凯凯我们等你回来 2024-12-18 18:27:51
SELECT t.Day, 
       t.OrderCount, 
       (SELECT SUM(t1.OrderCount) FROM table t1 WHERE t1.Day <= t.Day) 
         AS OrderCountRunningValue
FROM table t
SELECT t.Day, 
       t.OrderCount, 
       (SELECT SUM(t1.OrderCount) FROM table t1 WHERE t1.Day <= t.Day) 
         AS OrderCountRunningValue
FROM table t
红颜悴 2024-12-18 18:27:51
SELECT 
  t.day, 
  t.orderCount, 
  SUM(t1.orderCount) orderCountRunningValue
FROM 
  table t INNER JOIN table t1 ON t1.day <= t.day
group by t.day,t.orderCount
SELECT 
  t.day, 
  t.orderCount, 
  SUM(t1.orderCount) orderCountRunningValue
FROM 
  table t INNER JOIN table t1 ON t1.day <= t.day
group by t.day,t.orderCount
一城柳絮吹成雪 2024-12-18 18:27:51

CTE(再次)来救援:

DROP TABLE tmp.sums;
CREATE TABLE tmp.sums
        ( id INTEGER NOT NULL
        , zdate timestamp not null
        , amount integer NOT NULL
        );

INSERT INTO tmp.sums (id,zdate,amount) VALUES
 (1, '2011-10-24', 1 ),(1, '2011-10-25', 2 ),(1, '2011-10-26', 3 )
,(2, '2011-10-24', 11 ),(2, '2011-10-25', 12 ),(2, '2011-10-26', 13 )
        ;

WITH RECURSIVE list AS (
-- Terminal part
    SELECT  t0.id, t0.zdate
    , t0.amount AS amount
    , t0.amount AS runsum
    FROM tmp.sums t0
    WHERE NOT EXISTS (
        SELECT * FROM tmp.sums px
        WHERE px.id = t0.id
        AND px.zdate < t0.zdate
        )
    UNION
    -- Recursive part
    SELECT  p1.id AS id
    , p1.zdate AS zdate
    , p1.amount AS amount
    , p0.runsum + p1.amount AS runsum
    FROM tmp.sums AS p1
    , list AS p0
    WHERE p1.id = p0.id
    AND p0.zdate < p1.zdate
    AND NOT EXISTS (
        SELECT * FROM tmp.sums px
        WHERE px.id = p1.id
        AND px.zdate < p1.zdate
        AND px.zdate > p0.zdate
        )
    )
SELECT * FROM list
ORDER BY id, zdate;

输出:

DROP TABLE
CREATE TABLE
INSERT 0 6
 id |        zdate        | amount | runsum 
----+---------------------+--------+--------
  1 | 2011-10-24 00:00:00 |      1 |      1
  1 | 2011-10-25 00:00:00 |      2 |      3
  1 | 2011-10-26 00:00:00 |      3 |      6
  2 | 2011-10-24 00:00:00 |     11 |     11
  2 | 2011-10-25 00:00:00 |     12 |     23
  2 | 2011-10-26 00:00:00 |     13 |     36
(6 rows)

CTE's to the rescue (again):

DROP TABLE tmp.sums;
CREATE TABLE tmp.sums
        ( id INTEGER NOT NULL
        , zdate timestamp not null
        , amount integer NOT NULL
        );

INSERT INTO tmp.sums (id,zdate,amount) VALUES
 (1, '2011-10-24', 1 ),(1, '2011-10-25', 2 ),(1, '2011-10-26', 3 )
,(2, '2011-10-24', 11 ),(2, '2011-10-25', 12 ),(2, '2011-10-26', 13 )
        ;

WITH RECURSIVE list AS (
-- Terminal part
    SELECT  t0.id, t0.zdate
    , t0.amount AS amount
    , t0.amount AS runsum
    FROM tmp.sums t0
    WHERE NOT EXISTS (
        SELECT * FROM tmp.sums px
        WHERE px.id = t0.id
        AND px.zdate < t0.zdate
        )
    UNION
    -- Recursive part
    SELECT  p1.id AS id
    , p1.zdate AS zdate
    , p1.amount AS amount
    , p0.runsum + p1.amount AS runsum
    FROM tmp.sums AS p1
    , list AS p0
    WHERE p1.id = p0.id
    AND p0.zdate < p1.zdate
    AND NOT EXISTS (
        SELECT * FROM tmp.sums px
        WHERE px.id = p1.id
        AND px.zdate < p1.zdate
        AND px.zdate > p0.zdate
        )
    )
SELECT * FROM list
ORDER BY id, zdate;

The output:

DROP TABLE
CREATE TABLE
INSERT 0 6
 id |        zdate        | amount | runsum 
----+---------------------+--------+--------
  1 | 2011-10-24 00:00:00 |      1 |      1
  1 | 2011-10-25 00:00:00 |      2 |      3
  1 | 2011-10-26 00:00:00 |      3 |      6
  2 | 2011-10-24 00:00:00 |     11 |     11
  2 | 2011-10-25 00:00:00 |     12 |     23
  2 | 2011-10-26 00:00:00 |     13 |     36
(6 rows)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文