1

我想做一个产品数据库。每个产品的特征描述为一组 x 值和相应的 y 值。我想查询产品的某些特征。

示例产品数据:

ProductA_x = [10, 20, 30, 40, 50]
ProductA_y = [2, 10, 30, 43, 49]

ProductB_x = [11, 22, 33, 44, 55, 66]
ProductB_y = [13, 20, 42, 35, 28, 21]

现在我想获得 y < 35 @ x=31 的产品列表。在示例数据案例中,我应该得到 ProductA。

  • 如果我使用 MySQL,那么定义表以在 SQL 级别实现此查询的好方法是什么?
  • 如果我可以使用 PostgreSQL,会变得更容易吗?(使用 Array 或 JSON 类型??)

我被建议的一种方法是制作一个表格来指定 x 范围的 xy 对。第一个数据用于范围 x[0] 到 x[1],下一个数据用于 x[1] 到 x[2]。像这样的东西。

| ProductID | x1 | x2 | y1 | y2 |
| --------- | -- | -- | -- | -- |
| 1 | 10 | 20 | 2 | 10 |
| 1 | 20 | 30 | 10 | 30 |
| 1 | 30 | 40 | 30 | 43 |
| 1 | 40 | 50 | 43 | 49 |
| 2 | 11 | 22 | 33 | 44 |
| 2 | 22 | 33 | 20 | 42 |
| 2 | 33 | 44 | 42 | 35 |
| 2 | 44 | 55 | 35 | 28 |
| 2 | 55 | 66 | 28 | 21 |

然后我可以查询 (x1 > 31 AND 31 < x2) AND (y1 < 35 OR y2 < 35)

这个解决方案还不错,但我想知道是否有更聪明的方法。

请注意,x 数组保证是递增的,但不同的产品会有不同的起始 x 值、步长和点数。并且要搜索的 x 值可能不作为 x 数组中的确切值存在。实际 x 和 y 数组的长度约为 2000。我希望我有大约 10,000 个产品。

如果可以对相应的 y 值进行插值,但在最近的 x 值处搜索 y 值是可以接受的,那将是最好的。

4

1 回答 1

0

由于每个 X 都恰好对应一个 Y,因此经典关系数据库上的合理表定义将是:

CREATE TABLE product (id serial not null unique, sku text primary key, ....);
CREATE TABLE product_xy (product_id int not null references product(id),
                         x int not null,
                         y int not null,
                         primary key(product_id, x));

这将使您的查询在所有情况下都易于管理。

在 PostgreSQL 9.3 上,您可以使用 LATERAL 子查询来有效地使用数组,但我认为这不会比从关系设计开始更容易。您希望将信息存储在 PostgreSQL 中的数组中的唯一情况是序数对 x 数组很重要。然后设计变得稍微复杂一些,因为以下数组组合在语义上并不相同:

 array[1, 2, 3] x
 array[4, 5, 6] y

 array[2, 1, 3] x
 array[5, 4, 6] y

如果需要区分它们,那么在 PostgreSQL 中使用基于数组的解决方案(请注意,在这两种情况下,相同的 x 值对应于相同的 y 值,但对的顺序不同)。否则使用标准的关系设计。如果你必须这样做,那么你更好的选择是拥有一个二维 xy 数组,它类似于:

 array[
    array[1, 2, 3],
    array[4, 5, 6]
 ] xy

然后,您可以拥有可以将数组上的这些对作为一个整体进行处理的函数,但关键是在这种情况下,xy 表示特定域中的单个原子值,其中序数在两个维度上都很重要,因此可以处理该值立刻。换句话说,如果序数在两个维度上都很重要,那么您的域中只有一个值,因此这不会违反第一范式。如果沿任一维度的序数无关紧要,那么它确实违反了第一范式。

于 2013-11-16T05:03:34.573 回答