Sql 数据库,并且不是在应用程序中动态生成的,对吗?@EstericScreenName它是在我的应用程序中动态生成的。创建一个包含两个参数的存储过程,例如开始日期、结束日期,除非我遗漏了什么…这似乎没有任何实际作用(至少在我的查询和postgres中没有)。它

Sql 数据库,并且不是在应用程序中动态生成的,对吗?@EstericScreenName它是在我的应用程序中动态生成的。创建一个包含两个参数的存储过程,例如开始日期、结束日期,除非我遗漏了什么…这似乎没有任何实际作用(至少在我的查询和postgres中没有)。它,sql,ruby-on-rails,postgresql,sum,query-optimization,Sql,Ruby On Rails,Postgresql,Sum,Query Optimization,数据库,并且不是在应用程序中动态生成的,对吗?@EstericScreenName它是在我的应用程序中动态生成的。创建一个包含两个参数的存储过程,例如开始日期、结束日期,除非我遗漏了什么…这似乎没有任何实际作用(至少在我的查询和postgres中没有)。它只在之间取第一个,然后使用它并忽略其他记录。在postgres中可能是这样,但在SQL Server中,它将返回指定日期之间的所有记录。请注意,我留下了您的参数,并在您的参数中添加了多个OR,因此它将(应该)匹配您在一个查询中需要的所有内容。请



数据库,并且不是在应用程序中动态生成的,对吗?@EstericScreenName它是在我的应用程序中动态生成的。创建一个包含两个参数的存储过程,例如开始日期、结束日期,除非我遗漏了什么…这似乎没有任何实际作用(至少在我的查询和postgres中没有)。它只在之间取第一个
,然后使用它并忽略其他记录。在postgres中可能是这样,但在SQL Server中,它将返回指定日期之间的所有记录。请注意,我留下了您的参数,并在您的参数中添加了多个OR,因此它将(应该)匹配您在一个查询中需要的所有内容。请尝试广泛的日期,像
'2013-11-01'和'2013-11-15'
2013-12-15'和'2013-12-31'
,看看您是否从11月和12月获得结果…@Shpigford您的实现可能有问题,因为这应该可以正常工作。请参阅。我需要每个日期范围都有其关联的总和。所以在@jbwebtech的例子中,按顺序返回4个不同的数字。我得到了一个关于这个实现的例子。只是做了一些进一步的挖掘,看起来Rails中不支持过程(但这会节省任何数据库调用吗?这是这里的问题…必须进行大量查询。是和否。根据定义,这只会是一个调用,但由于每个日期范围都是线性获取的,因此仍然有多个子查询。因此,这实际上只打开一个到数据库的连接,而我以前的方法必须打开数百个连接…对吗?在查询中不做
求和
,而是用Ruby来处理,这有意义吗?不,SQL中的求和比代码循环更有效。根据我的经验,我得到了一个
错误:列“开始日期”不存在
错误。可能是语法问题吗?不确定Postgres的正确方法是什么。如果您在中设置了带有一些测试数据的架构,那么我将尝试在其中运行。添加前缀“句点”对于前3行中的开始日期和结束日期列,它是有效的…似乎PostgreSQL比我在TSQL=)中使用的要挑剔一点)为什么需要在“余额交易”时使用
CASE“.”在“期间”之间创建“.”开始日期“和”期间“.”结束日期“
选择
部分,因为我们已经有了
按“期间分组”“开始日期”、“句点”、“结束日期”
?我没有注意到您正在Postgre上工作。无论如何,我在看Postgre文档,它实际上受到XML使用的支持:PostgreXML支持:您可以将此代码转换为Postgre方法
SELECT 
   SUM("balance_transactions"."fee") AS sum_id 
   FROM "balance_transactions" 
   JOIN charges ON balance_transactions.source = charges.balance_id 
   WHERE "balance_transactions"."account_id" = 6 
      AND (balance_transactions.type = 'charge' 
      AND charges.refunded = false 
      AND charges.invoice IS NOT NULL) 
      AND ("balance_transactions"."created" BETWEEN '2013-12-20' AND '2014-01-19');
2013-12-20 to 2014-01-19
2013-12-21 to 2014-01-20
2013-12-22 to 2014-01-21
2013-12-23 to 2014-01-22
2013-12-24 to 2014-01-23
...so on and so on
...
AND (
      "balance_transactions"."created" BETWEEN '2013-12-20' AND '2014-01-19'
      OR
      "balance_transactions"."created" BETWEEN '2013-12-21' AND '2014-01-20'
      OR
      "balance_transactions"."created" BETWEEN '2013-12-23' AND '2014-01-22'
      OR
      "balance_transactions"."created" BETWEEN '2013-12-24' AND '2014-01-23'
    );
CREATE OR REPLACE PROCEDURE sum_fees(v_start IN Date, v_end in Date) IS

BEGIN
  SELECT 
   SUM("balance_transactions"."fee") AS sum_id 
   FROM "balance_transactions" 
       JOIN charges ON balance_transactions.source = charges.balance_id 
   WHERE "balance_transactions"."account_id" = 6 
      AND (balance_transactions.type = 'charge' 
      AND charges.refunded = false 
      AND charges.invoice IS NOT NULL) 
      AND ("balance_transactions"."created" BETWEEN v_start AND v_end);
END;
SELECT 
   'a' AS DateRangeIdentifier,
   SUM("balance_transactions"."fee") AS sum_id 
   FROM "balance_transactions" 
   JOIN charges ON balance_transactions.source = charges.balance_id 
   WHERE "balance_transactions"."account_id" = 6 
      AND (balance_transactions.type = 'charge' 
      AND charges.refunded = false 
      AND charges.invoice IS NOT NULL) 
      AND ("balance_transactions"."created" BETWEEN '2013-01-01' AND '2013-01-31')

UNION 

SELECT 
   'b' AS DateRangeIdentifier,
   SUM("balance_transactions"."fee") AS sum_id 
   FROM "balance_transactions" 
   JOIN charges ON balance_transactions.source = charges.balance_id 
   WHERE "balance_transactions"."account_id" = 6 
      AND (balance_transactions.type = 'charge' 
      AND charges.refunded = false 
      AND charges.invoice IS NOT NULL) 
      AND ("balance_transactions"."created" BETWEEN '2013-07-01' AND '2013-07-31')

UNION 

SELECT 
   'c' AS DateRangeIdentifier,
   SUM("balance_transactions"."fee") AS sum_id 
   FROM "balance_transactions" 
   JOIN charges ON balance_transactions.source = charges.balance_id 
   WHERE "balance_transactions"."account_id" = 6 
      AND (balance_transactions.type = 'charge' 
      AND charges.refunded = false 
      AND charges.invoice IS NOT NULL) 
      AND ("balance_transactions"."created" BETWEEN '2013-12-20' AND '2014-01-19')

GROUP BY DateRangeIdentifier, sum_id
SELECT "periods"."start_date", 
       "periods"."end_date", 
       SUM(CASE WHEN "balance_transactions"."created" BETWEEN "periods"."start_date" AND "periods"."end_date" THEN "balance_transactions"."fee" ELSE 0.00 END) AS period_sum
  FROM "balance_transactions" 
  JOIN charges ON balance_transactions.source = charges.balance_id 
  JOIN ( SELECT '2013-12-20'::date as start_date, '2014-01-19'::date as end_date UNION ALL
         SELECT '2013-12-21'::date as start_date, '2014-01-20'::date as end_date UNION ALL
         SELECT '2013-12-22'::date as start_date, '2014-01-21'::date as end_date UNION ALL
         SELECT '2013-12-23'::date as start_date, '2014-01-22'::date as end_date UNION ALL
         SELECT '2013-12-24'::date as start_date, '2014-01-23'::date as end_date
         ) as periods
    ON "balance_transactions"."created" BETWEEN "periods"."start_date" AND "periods"."end_date"
 WHERE "balance_transactions"."account_id" = 6 
   AND "balance_transactions"."type" = 'charge' 
   AND "charges"."refunded" = false 
   AND "charges"."invoice" IS NOT NULL
 GROUP BY "periods"."start_date", "periods"."end_date"
SELECT 
   SUM("balance_transactions"."fee") AS sum_id 
   FROM "balance_transactions" 
   JOIN charges ON balance_transactions.source = charges.balance_id 
   WHERE "balance_transactions"."account_id" = 6 
      AND (balance_transactions.type = 'charge' 
      AND charges.refunded = false 
      AND charges.invoice IS NOT NULL) 
      AND ("balance_transactions"."created" = 'yyyy-mm-dd');
insert into sum_table
SELECT 
   "balance_transactions"."created" balance_created
   SUM("balance_transactions"."fee") AS balance_fee 
   FROM "balance_transactions" 
   JOIN charges ON balance_transactions.source = charges.balance_id 
   WHERE "balance_transactions"."account_id" = 6 
      AND (balance_transactions.type = 'charge' 
      AND charges.refunded = false 
      AND charges.invoice IS NOT NULL) 
   group by "balance_transactions"."created"
;
SELECT 
   SUM(balance_fee) AS sum_id 
   FROM sum_table where balance_created between ('2013-12-20' AND '2014-01-19');
SELECT 
   SUM(balance_fee) AS sum_id 
   FROM sum_table where balance_created in ('2013-12-20', '2013-12-21', '2013-12-22' ... '2014-01-19');
select distinct on (s.d)
    s.d as "date",
    sum(bt.fee) over (
        partition by daterange(s.d, (s.d + interval '1 month')::date, '[]')
    ) as sum_id
from
    balance_transactions bt
    inner join
    charges on bt.source = charges.balance_id
    right join
    (
        select d::date as d
        from generate_series (
            '2013-12-20'::date,
            current_date,
            interval '1 day'
        ) s(d)
    ) s on s.d = bt.created
where
    bt.account_id = 6
    and bt.type = 'charge'
    and charges.refunded = false
    and charges.invoice is not null
order by s.d
select array_agg(("date", sum_id)) as arr_sum_id
from (
    select distinct on (s.d)
        s.d as "date",
        sum(bt.fee) over (
            partition by daterange(s.d, (s.d + interval '1 month')::date, '[]')
        ) as sum_id
    from
        balance_transactions bt
        inner join
        charges on bt.source = charges.balance_id
        right join
        (
            select d::date as d
            from generate_series (
                '2013-12-20'::date,
                current_date,
                interval '1 day'
            ) s(d)
        ) s on s.d = bt.created
    where
        bt.account_id = 6
        and bt.type = 'charge'
        and charges.refunded = false
        and charges.invoice is not null
    order by s.d
) s
create table timeframes (
    start_dt date,
    end_dt date
);

insert into timeframes values ('2013-12-20', '2014-01-19');
insert into timeframes values ('2013-12-21', '2014-01-20');
insert into timeframes values ('2013-12-22', '2014-01-21');
insert into timeframes values ('2013-12-23', '2014-01-22');
insert into timeframes values ('2013-12-24', '2014-01-23');

SELECT 
    tf.start_date, 
    tf.end_date, 
    SUM(CASE 
        WHEN t.created BETWEEN tf.start_date AND tf.end_date THEN t.fee
        ELSE 0.00 
    END) as transaction_sum
FROM 
    balance_transactions t
INNER JOIN 
    charges c
ON 
    t.source = c.balance_id 
INNER JOIN 
    timeframes tf
ON 
    t.created BETWEEN tf.start_date AND tf.end_date
WHERE 
    t.account_id = 6
AND 
    (
    t.type = 'charge' 
        AND 
    c.refunded = false 
        AND 
    c.invoice IS NOT NULL
    ) 
GROUP BY
    tf.start_date, 
    tf.end_date
SELECT periods.start_date, 
     periods.end_date, 
     SUM(fee) AS Period_Sum
FROM "balance_transactions" 
JOIN charges ON balance_transactions.source = charges.balance_id 
JOIN
(SELECT CAST('2013-12-20' AS DATE) AS start_date, CAST('2014-01-19' AS DATE) AS end_date UNION     ALL
 SELECT  CAST('2013-12-21' AS DATE),CAST('2014-01-20'  AS DATE) UNION ALL
 SELECT  CAST('2013-12-22' AS DATE),  CAST('2014-01-21' AS DATE) UNION ALL
 SELECT CAST('2013-12-23' AS DATE),  CAST('2014-01-22' AS DATE) UNION ALL
 SELECT  CAST('2013-12-24' AS DATE), CAST('2014-01-23' AS DATE)) as periods
ON "balance_transactions"."created" BETWEEN periods.start_date AND periods.end_date
WHERE "balance_transactions"."account_id" = 6 
AND (balance_transactions.type = 'charge' 
AND charges.refunded = false 
AND charges.invoice IS NOT NULL) 
GROUP BY periods.start_date, periods.end_date
/*****************CREATES/POPULATES FAKE TABLES WITH A SIMILAR STRUCTURE TO THE ONE YOU ARE USING************/
DECLARE @balance_transactions TABLE(fee FLOAT,
                                    source INT,
                                    account_id INT,
                                    [type] VARCHAR(25),
                                    created DATETIME)

INSERT INTO @balance_transactions
SELECT 12.5, 1, 6, 'charge', '01/15/2012'
UNION
SELECT 70, 2, 6, 'charge', '01/16/2012'
UNION
SELECT 136.89, 3, 6, 'charge', '01/17/2012'
UNION
SELECT 29.16, 4, 6, 'charge', '01/18/2012'
UNION
SELECT 1369.54, 5, 6, 'charge', '02/21/2012'
UNION
SELECT 468.85, 6, 6, 'charge', '02/22/2012'
UNION
SELECT 65.8, 7, 6, 'charge', '02/22/2012'
UNION
SELECT 1236.87, 8, 6, 'charge', '02/22/2012'

DECLARE @charges TABLE(balance_id INT,
                       refunded BIT,
                       invoice INT)

INSERT INTO @charges
SELECT 1, 0, 7
UNION
SELECT 2, 0, 8
UNION
SELECT 3, 0, 9
UNION
SELECT 4, 0, 10
UNION
SELECT 5, 0, 11
UNION
SELECT 6, 0, 12
UNION
SELECT 7, 0, null
UNION
SELECT 8, 0, null
/*******************************************************/

/*
You can use the code below for creating an Stored Procedure.
The SP will return a table with the SUM of all those values indicating the Date Range.

spGetTotalsPerDateRange 'your xml goes here'

results:

fromDate                |toDate                     |total
2012-01-15 00:00:00.000 |2012-01-30 00:00:00.000    |248.55
2012-02-15 00:00:00.000 |2012-02-28 00:00:00.000    |3141.06
*/
SET DATEFORMAT MDY

DECLARE @XmlDocumentHandle int
DECLARE @XmlDocument nvarchar(4000)
SET @XmlDocument = 
N'<dates>
    <range>
       <fromDate>01/15/2012</fromDate>
       <toDate>01/30/2012</toDate>
    </range>
    <range>   
       <fromDate>02/15/2012</fromDate>
       <toDate>02/28/2012</toDate>
    </range>
</dates>'

EXEC sp_xml_preparedocument @XmlDocumentHandle OUTPUT, @XmlDocument

DECLARE @feeTotal TABLE(fromDate DATETIME,
                        toDate DATETIME,
                        total FLOAT)


DECLARE @fromDate DATETIME
DECLARE @toDate DATETIME
DECLARE ranges_cur CURSOR FOR

SELECT fromDate, toDate
FROM OPENXML (@XmlDocumentHandle, '/dates/range',2)
     WITH (fromDate  DATETIME,
           toDate DATETIME);

OPEN ranges_cur;
FETCH NEXT FROM ranges_cur INTO @fromDate, @toDate;
WHILE @@FETCH_STATUS = 0
   BEGIN
      INSERT INTO @feeTotal
      SELECT @fromDate, 
             @toDate,
             SUM(bt.fee)
      FROM @balance_transactions bt
      INNER JOIN @charges c ON bt.source = c.balance_id 
      WHERE bt.account_id = 6 
      AND (bt.type = 'charge' 
      AND c.refunded = 0 
      AND c.invoice IS NOT NULL)
      AND (bt.created >= @fromDate AND bt.created <= @toDate);

      FETCH NEXT FROM ranges_cur INTO @fromDate, @toDate;
   END;
CLOSE ranges_cur;
DEALLOCATE ranges_cur;

SELECT fromDate,
       toDate,
       total
FROM @feeTotal

EXEC sp_xml_removedocument @XmlDocumentHandle

GO
CREATE PROCEDURE spGetTotalsPerDateRange(@XmlDocument NVARCHAR(4000),
                                         @type VARCHAR(50) = 'charge',
                                         @refunded BIT = 0)
AS
BEGIN
    SET DATEFORMAT MDY

    DECLARE @XmlDocumentHandle INT
    EXEC sp_xml_preparedocument @XmlDocumentHandle OUTPUT, @XmlDocument

    DECLARE @feeTotal TABLE(fromDate DATETIME,
                            toDate DATETIME,
                            total FLOAT)


    DECLARE @fromDate DATETIME
    DECLARE @toDate DATETIME
    DECLARE ranges_cur CURSOR FOR

    SELECT fromDate, toDate
    FROM OPENXML (@XmlDocumentHandle, '/dates/range',2)
         WITH (fromDate  DATETIME,
               toDate DATETIME);

    OPEN ranges_cur;
    FETCH NEXT FROM ranges_cur INTO @fromDate, @toDate;
    WHILE @@FETCH_STATUS = 0
       BEGIN
          INSERT INTO @feeTotal
          SELECT @fromDate, 
                 @toDate,
                 SUM(bt.fee)
          FROM balance_transactions bt
          INNER JOIN charges c ON bt.source = c.balance_id 
          WHERE bt.account_id = 6 
          AND (bt.type = 'charge' 
          AND c.refunded = 0 
          AND c.invoice IS NOT NULL)
          AND (bt.created >= @fromDate AND bt.created <= @toDate);

          FETCH NEXT FROM ranges_cur INTO @fromDate, @toDate;
       END;
    CLOSE ranges_cur;
    DEALLOCATE ranges_cur;

    SELECT fromDate,
           toDate,
           total
    FROM @feeTotal

    EXEC sp_xml_removedocument @XmlDocumentHandle

END
GO
SELECT DISTINCT account_id,
  TRUNC(created)
  ||' to '
  || (TRUNC(created)+1) period,
  SUM(FEE) over (partition BY account_id,TRUNC(created) ) sumid
FROM balance_transactions a,
  charges b
WHERE a.source =balance_id
AND b.refunded =0
AND b.invoice IS NOT NULL
AND a.type     ='charge'
ORDER BY TRUNC(created)
  ||' to '
  || (TRUNC(created)+1);