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