在MySQL视图中使用派生表达式

时间:2010-01-07 17:15:08

标签: sql mysql

这里的示例显示了我在MySQL中构建的{em>非常简化版本的VIEW。这里的目标是创建一个视图,我可以从中选择要将一组结果填充到HTML表中。

我使用视图的目的部分是将此数据的计算显示为视图中的列。我可以通过为表达式提供别名来轻松完成此操作,例如:SELECT a, b, a + b AS c将为我提供一个包含三列的结果集,其中c列中的值是列{{1}中的值的添加}和a

示例1

这就是我目前正在构建一个虚构的“产品库存”表格的视图:

b

能够同时显示库存缺口和更换表中的库存成本对我来说非常重要。您可以看到这没有完全优化,因为再次使用库存短缺计算的一部分来计算成本。

这也意味着,如果计算出股票短缺的计算方式发生变化,则需要对股票短缺成本进行相同的变更,从而增加维护代码的难度。

实施例2(理想的溶液)

我可以创建一个这样的SELECT语句,这将允许我使用用户变量引用过去的表达式:

SELECT
  description,
  unit_cost,
  current_stock,
  required_stock,

  (required_stock - current_stock)                     AS stock_shortfall,
  (required_stock - current_stock) * unit_cost         AS stock_shortfall_cost
FROM product_stock

通过在进一步的计算中引用表达式的别名,我也可以通过对派生表使用子查询来实现类似的效果。

不幸,MySQL不允许我在SELECT description, unit_cost, current_stock, required_stock, @stock_shortfall := (required_stock - current_stock) AS stock_shortfall, @stock_shortfall * unit_cost AS stock_shortfall_cost FROM product_stock 内使用用户变量派生表子查询。< / p>

另一种解决方案可能是创建一个视图来代替派生表,并为每个重用的表达式创建另一个视图“图层”以从中选择派生值。这有效,但经过这么多层次之后,它也变得无法维护。

我目前正在执行“分层”视图和重复计算的混合,如示例#1中所示。请理解,我希望构建的实际VIEW是8个表中的VIEW,其中包含大量计算值,可在整个表达式中重复使用。它不太可管理。

感谢您阅读我的文字墙。以下是我的问题:

是否可以使用与示例#2类似的方式使用派生表达式创建JOIN? 如果没有,你会如何解决这个问题?

最佳解决方案是什么?我应该使用服务器端脚本来计算值而不是使用数据库吗?是否有其他数据库技术支持此功能?你会做什么?

4 个答案:

答案 0 :(得分:3)

最后,我写了SELECT语句,类似于我在第二个例子(理想的解决方案)中编写的语句,它不能用于构造VIEW

然后我写了一个小编译器来从该语句创建一个更复杂的查询,可用于构造VIEW

现在维护起来要容易得多。

感谢Rob Van Dam鼓励我编译查询。

答案 1 :(得分:1)

这些查询的客户端是什么?如果您使用的是任何编程语言(而不是瘦Web客户端),那么您可以使用该语言构建查询(perl / php示例):

$stock_shortfall = "(required_stock - current_stock)";
$query = "SELECT
  description,
  unit_cost,
  current_stock,
  required_stock,

  $stock_shortfall                     AS stock_shortfall,
  $stock_shortfall * unit_cost         AS stock_shortfall_cost
FROM product_stock"

如果您可能需要经常重复使用此查询,那么您可以围绕它构建一个类,或者至少有一个生成查询字符串的静态库类。

答案 2 :(得分:0)

我们基本上在做同样的工作 - &gt;除了BLOBS,意味着每个派生/临时表都自动写入磁盘。

这是绝对的性能杀手。

此外,MySQL 5.0(我们正在使用的)不支持索引VIEW,因此每次查询完成时都需要全表扫描才能获取1个结果!

然而,有希望。

我从未使用过这个功能,但PostgreSQL支持物化视图。因此,我的理解是,当你计算所有讨厌的子查询时,它会将计算结果保存在VIEW中,直到其中一个底层字段发生变化(告诉我这里是不是错了,Postgres devs / DBAs)。

此外,我们无法更改为Postgres,因此我们制作了一个cron文件,仅每5分钟构建一次VIEW并存储一个静态计算版本,从而使性能更好。我认为基准测试好10倍。但是,这取决于您是否愿意暂时使用陈旧数据......

答案 3 :(得分:0)

使用FUNCTION可能会利用可维护性......并且希望(在不久的将来)它也可以提升性能。

SELECT
  ...
  stock_shortfall(required_stock, current_stock),
  stock_shortfall_cost(required_stock, current_stock, unit_cost)
...

这两个函数应标记为DETERMINISTIC。在MySql 5.0中,优化器未使用该特性。我不知道以后的版本是否已经使用它(所以“不久的将来”参考)。

当然,简单的单次使用计算很少值得CREATE FUNCTION...打字开销。