我正在对包含超过1.2亿行和200列的数据库运行查询。数据集包含贷款信息,我们为每个借款人提供大约15行(每季度一次观察),而borrowerID也是主要密钥。我也加入了这个borrowerID来检索上一季度的信息,我明白这使得我的查询非常复杂。该数据库还包含Bank上的FK(外键)。托管数据库的一方向我解释说,如果我编写一个函数来按部分运行查询,那么它会更快。目前我的查询看起来像这样。
SELECT a.id.
a.arrears AS "Months in Arrears",
a.balance AS "Original Balance",
a.bank AS "Bank",
b.arrears AS "Next Months in Arrears",
b.balance AS "Next Original Balance",
dense_rank() OVER (PARTITION BY concat(a.bank, a.id), ("substring"(a.date::text, 1, 4) || 'Q'::text) || round(0.3333 + "substring"(a.date::text, 6, 2)::numeric / 3::numeric, 0) ORDER BY a.date DESC) AS "Duplicate",
FROM loandata a
LEFT JOIN loandata b ON a.bank::text = b.bank::text AND a.id::text = b.id::text AND round((b.date::date - a.date::date)::numeric / 30::numeric, 0) = 3::numeric
ALTER TABLE myview
OWNER TO me;
GRANT ALL ON TABLE myview TO me;
你能帮我写一个函数,这个查询是由银行执行的,或者每个id执行它是否有意义,因为它是主键?我正在运行此视图以在Tableau中下载和存储数据。
非常感谢提前。 最好的,蒂姆
PS。 dense_rank函数用于查找每季度有多个观察值的贷款。
评论中建议的解释分析结果可以在这里找到: http://explain.depesz.com/s/K19 我使用了数据的一个子集,我选择了1个银行。
答案 0 :(得分:2)
我不太确定查询的确切意图,但使用日期函数而不是数值类型的计算,并且避免所有强制转换和concat()可能会让你到达某个地方。
SELECT a.id
, a.arrears AS "Months in Arrears"
, a.balance AS "Original Balance"
, a.bank AS "Bank"
, b.arrears AS "Next Months in Arrears"
, b.balance AS "Next Original Balance"
, dense_rank() OVER (
PARTITION BY a.bank, a.id, date_trunc( 'quarter' ,a.date )
ORDER BY a.date DESC
) AS "Duplicate"
FROM loandata a
LEFT JOIN loandata b ON a.bank = b.bank
AND a.id = b.id
AND date_trunc( 'quarter', b.date )
= date_trunc( 'quarter', a.date + 'quarter'::interval) )
;
BTW:不要使用名为date
的列。它是SQL中的类型名称(在我的编辑器中以绿色突出显示)
答案 1 :(得分:0)
我建议修改一下:
LEFT JOIN loandata b ON a.bank::text = b.bank::text AND a.id::text = b.id::text AND round((b.date::date - a.date::date)::numeric / 30::numeric, 0) = 3::numeric
...到......
LEFT JOIN loan data b
ON a.bank = b.bank AND
a.id = b.id AND
b.date between (a.date + 75) and (a.date + 105)
虽然,我不确定你的日期逻辑是你想要的。如果您可以用文字描述您想要的内容,那么可以使用更好的方法。
https://wiki.postgresql.org/wiki/Working_with_Dates_and_Times_in_PostgreSQL