【问题标题】:MySQL apply filter on joined tableMySQL 在连接表上应用过滤器
【发布时间】:2020-01-18 09:42:24
【问题描述】:

假设我们有一个包含物理立方体的数据库,定义为对象。每个对象都有长度、宽度和高度。如下例所示。

CREATE TABLE dimensions(
    id int PRIMARY KEY NOT NULL,
    value int
);

CREATE TABLE object(
    id int,
    dimension VARCHAR(100),
    dimension_value_id int,
    FOREIGN KEY (dimension_value_id) REFERENCES dimensions(id)
);

INSERT INTO dimensions VALUES(0, 100);
INSERT INTO dimensions VALUES(1, 200);
INSERT INTO dimensions VALUES(2, 300);
INSERT INTO dimensions VALUES(3, 400);

INSERT INTO object VALUES(0, "length", 1);
INSERT INTO object VALUES(0, "width", 3);
INSERT INTO object VALUES(0, "height", 2);

INSERT INTO object VALUES(1, "length", 1);
INSERT INTO object VALUES(1, "width", 1);
INSERT INTO object VALUES(1, "height", 2);

我的目标是过滤尺寸小于 251x251x350 的对象,在示例中这将是 id 为 1 的对象。

加入表格时,我得到记录:

SELECT * FROM object o
JOIN dimensions d ON o.dimension_value_id = d.id

但是现在如何应用过滤器。我遇到了存在/不存在的解决方案。但在这种情况下,这是行不通的,因为我需要一个不存在的独占。 如何实现?

【问题讨论】:

  • 这些可能是长方体,但它们不是正方形?!?!?顺便说一句,INT 声明后括号中的数字几乎完全没有意义——在这种情况下也是如此,因为所描述的允许数字将大于宇宙中的原子数。
  • 比什么更小?所有尺寸还是体积?
  • 与所有维度相比。方向也应该被忽略,这意味着如果需要,我想旋转以达到更小的条件,独立于原始方向。
  • 这是否意味着对象的 3 个维度中的较大者必须小于 3 个维度中的较小者:251x251x350 所以 251 才能旋转对象?
  • 假设我们有一个大小为 250x250x300 的对象,并想检查是否可以将其放入大小为 251x251x350 的盒子中。所以我们可以随意旋转,但我们不想。意味着如果给定的框是 251x350x251 或 350x251x251,我也想适合它。你明白我的意图吗?

标签: mysql sql join filter


【解决方案1】:

您可以使用条件聚合。这看起来像:

SELECT o.id 
FROM object o JOIN
     dimensions d 
     ON o.dimension_value_id = d.id
GROUP BY o.id 
HAVING MAX(CASE WHEN o.dimension = 'length' THEN d.value END)) < 350 AND
       MAX(CASE WHEN o.dimension = 'width' THEN s.value END)) < 350 AND
       MAX(CASE WHEN o.dimension = 'height' THEN d.value END)) < 350;

【讨论】:

    【解决方案2】:

    您必须将 3 个维度中较小的维度与 3 个值中的较小者进行比较,将最大维度与 3 个值中的最大值进行比较,将中间的维度与 3 个值的中间值进行比较:

    select o.id 
    from object o inner join dimensions d 
    on o.dimension_value_id = d.id
    group by o.id 
    having 
      min(d.value) < least(251, 251, 350) 
      and 
      max(d.value) < greatest(251, 251, 350)
      and
      max(case when o.dimension = 'length' then d.value end) + 
      max(case when o.dimension = 'width' then d.value end) +
      max(case when o.dimension = 'height' then d.value end) -
      (min(d.value) + max(d.value)) < 
      (251 + 251 + 350) - (least(251, 251, 350) + greatest(251, 251, 350))
    

    请参阅demo
    传递参数的简化版本,如251, 251, 350:

    select o.id 
    from object o inner join dimensions d 
    on o.dimension_value_id = d.id
    cross join (select 251 as col1, 251 as col2, 350 as col3) t
    group by o.id 
    having 
      min(d.value) < least(max(t.col1), max(t.col2), max(t.col3)) 
      and 
      max(d.value) < greatest(max(t.col1), max(t.col2), max(t.col3))
      and
      max(case when o.dimension = 'length' then d.value end) + 
      max(case when o.dimension = 'width' then d.value end) +
      max(case when o.dimension = 'height' then d.value end) -
      (min(d.value) + max(d.value)) < 
      (max(t.col1) + max(t.col2) + max(t.col3)) - (
        least(max(t.col1), max(t.col2), max(t.col3)) + 
        greatest(max(t.col1), max(t.col2), max(t.col3))
      )
    

    请参阅demo

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-21
      • 1970-01-01
      • 1970-01-01
      • 2013-02-11
      相关资源
      最近更新 更多