如何通过连接表的行(而不是列)中的值来订购mysql查询结果?

时间:2015-11-26 14:53:17

标签: mysql join

我有一张表items和一张表parametersitem_parameters的连接表存储项的每个可能参数的值,而不是为每个参数设置单独的列。

例如(简化):

parameters:             items:              
id: 1, name: color      id: 1, name: bike
id: 2, name: size       id: 2, name: phone
id: 3, name: weight     id: 3, name: shoe

item_parameters: 
id: 1, item_id: 1, parameter_id: 1, value: "blue"
id: 2, item_id: 1, parameter_id: 2, value: "large"
id: 3, item_id: 1, parameter_id: 3, value: "heavy"
id: 4, item_id: 2, parameter_id: 1, value: "black"
id: 5, item_id: 2, parameter_id: 2, value: "medium"
id: 6, item_id: 2, parameter_id: 3, value: "medium"
id: 7, item_id: 3, parameter_id: 1, value: "white"
id: 8, item_id: 3, parameter_id: 2, value: "small"
id: 9, item_id: 3, parameter_id: 3, value: "light"

如何搜索项目(应用特定参数的过滤器)并根据value的特定parameter的{​​{1}}排序结果?

我知道如何应用过滤器部分,使用带有items的where子句但是对于排序部分,仅仅添加item_parameters.parameter_id = ? AND item_parameters.value = ?似乎不足以仅按{{1}排序}} ORDER BY item_parameters.value desc

在我的项目结果中,我希望item_parameters.value的所有where item_parameters.parameter_id = ?包括未在order by子句中使用的item_parameters

此查询仍在进行中,因为我还没有为每个item返回所有parameters

item_parameters

另外目前还没有返回所有item_parameters,这篇文章上面的相关缺失部分是订单逻辑(伪代码)需要item

以下是所需结果的示例,假设比上面提供的示例更大的示例数据集:

 SELECT DISTINCT
         `items`.name,
         `parameters`.name,
         `item_parameters`.value
 FROM `items` 
 LEFT OUTER JOIN `item_parameters` ON `item_parameters`.`item_id` = `items`.`id`
 LEFT OUTER JOIN `parameters` ON `item_parameters`.`parameter_id` = `parameters`.`id`
 WHERE (item_parameters.parameter_id = 3 AND item_parameters.value = 'light') 
 ORDER BY item_parameters.value LIMIT 10000;

请注意,结果全部在参数3(weight)= light上过滤,并在参数1(颜色)上排序。

感谢您提供任何指导。

1 个答案:

答案 0 :(得分:1)

我不确定它对性能最好,但这是我在逻辑上构建查询的方式。

首先选择所有项目及其参数:

   SELECT i.name, p.name, ip.value
     FROM items i
     JOIN item_parameters ip
       ON ip.item_id = i.id
     JOIN parameters p
       ON p.id = ip.parameter_id

然后确保您只有具有特定参数的正确值的项目:

     JOIN item_parameters ip3
       ON ip3.parameter_id = 3
      AND ip3.item_id = i.id
      AND ip3.value = 'light'

然后包括您订购的参数:

     JOIN item_parameters ip1
       ON ip1.parameter_id = 1
      AND ip1.item_id = i.id

然后添加ORDER BY:

 ORDER BY ip1.value DESC, i.id, p.id

如果按照可能不存在的参数进行排序,则必须LEFT JOIN到该参数,并选择将结果为NULL值的位置。

这也不会如示例结果中所示那样转动表格,但会将项目组合在一起很好。

如果您希望使用旋转表,则可能需要单独加入所有参数,类似于上面的1和3。您可以手动执行此操作,也可以从预期/必需参数列表中动态构建查询。

<强>更新

对于显示的透视结果,有一点硬编码:

  SELECT i.name, color.value color, size.value size, weight.value weight
    FROM items i
    JOIN item_parameters color
      ON color.parameter_id = 1
     AND color.item_id = i.id
    JOIN item_parameters size
      ON size.parameter_id = 2
     AND size.item_id = i.id
    JOIN item_parameters weight
      ON weight.parameter_id = 3
     AND weight.item_id = i.id
   WHERE weight.value = 'light'
ORDER BY color.value DESC

您可以加入参数表以获取名称,以防它们发生变化,但这会为您提供一个大纲。

这种方法的缺点是每次添加新参数时都必须更新查询。

就个人而言,我更喜欢组样式方法,可以使用应用程序代码生成数据透视表。