gpt4 book ai didi

sql - 使用 Rails 在 Postgres 中开发自定义函数

转载 作者:数据小太阳 更新时间:2023-10-29 08:04:20 24 4
gpt4 key购买 nike

假设我有一个大型复合公式来计算小部件的质量

quality = 0.4(factory_quality) + 0.3(1/days_since_manufacture) + 0.3(materials_quality)

这三个因素中的每一个本身都是函数,它们需要连接到工厂表,并且可能需要连接到带有 Material 的 Material list 连接表,其中关联的记录是平均的或其他的。

在架构上,您将如何在 Rails 项目中管理它? a) 生成正确的查询和 b) 在 Rails 中管理代码的最佳实践是什么?

目前对于 sql,我在 FROM 语句中使用子查询:

SELECT *,
(0.4 * factory_quality + 0.3 * (1/days_since_manufacture) + 0.3 * materials_quality) AS quality
FROM (
SELECT *,
((factories.last_inspection_score + factories.variance_score)/2) AS factory_quality,
(now() - widgets.created_at) AS days_since_manufacture,
SUM(materials.quality_score) AS materials_quality
FROM widgets,
JOIN factories ON widget.factory_id = factories.id
JOIN bills_of_materials ON widget.id = bills_of_materials.widget_id
JOIN materials ON bills_of_materials.material_id = materials.id
GROUP BY widgets.id
) AS widgets;

在 Rails 中,我主要使用 ActiveRecord 来实现:

class Widget < ActiveRecord::Base
belongs_to :factory
has_many :bills_of_material
has_many :materials, through :bills_of_material

class << self
def with_quality
select([
"widgets.*",
"(0.4 * factory_quality + 0.3 * (1/days_since_manufacture) + 0.3 * materials_quality) AS quality"
].join(",")
.from("(#{subquery}) AS widgets")
end
private
def subquery
select([
"widgets.*",
"((factories.last_inspection_score + factories.variance_score)/2) AS factory_quality",
"(now() - widgets.created_at) AS days_since_manufacture",
"SUM(materials.quality_score) AS materials_quality"
].join(","))
.joins(:factory,:materials)
.group("widgets.id")
.to_sql
end
end
end

也就是说,我觉得我可以在 Postgres 中将其设为自定义函数,将所有这些 sql 移到该函数中,迁移它,然后清理 rails 使其看起来像

def with_scores
select("*,quality_score_func(id) AS quality")
end

或类似的东西,但我觉得通过数据库迁移来管理不断发展的公式会很痛苦,更不用说找出公式的当前形式的任务了是(而且也很难测试)。

其他人是如何解决这个问题的?有什么提示或建议吗?

最佳答案

这是我能想到的最不使用 SQL 的方法。我无法真正对此进行测试,但希望它至少是一个有用的练习。据我了解,如果您使用 includes,Rails 会将连接放在一起并在一个查询中预先加载所有相关数据。

# All of these are additional Widget instance methods; you decide if they are private
#
# Example use:
#
# @widget = Widget.includes(:factory, :materials).find(1)
# puts @widget.quality_score
# or
# @widgets = Widget.includes(:factory, :materials).all
# @widgets.each { |widget| puts widget.quality_score }

# Consider making these weights named constants
def quality_score
0.4 * factory_quality + \
0.3 * (1/days_since_manufacture) + \
0.3 * (materials_quality_score )
end

def days_since_manufacture
Time.now - created_at
end

def factory_quality
(factory.last_inspection_score + factory.variance_score)/2
end

def materials_quality_score
materials.inject(0) {|sum, material| sum + material.quality_score }
end

关于sql - 使用 Rails 在 Postgres 中开发自定义函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22386749/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com