【发布时间】:2012-07-28 13:24:34
【问题描述】:
这是我的表格的简化版本:
group price spec
a 1 .
a 2 ..
b 1 ...
b 2
c .
. .
. .
我想生成这样的结果:(我将其称为 result_table)
price_a |spec_a |price_b |spec_b |price_c ...|total_cost
1 |. |1 |.. |... |
(min) (min) =1+1+...
基本上我想:
- 选择每组中包含最低价格的行
- 将列合并为一行
我知道这可以使用多个查询和/或结合对结果的一些非 sql 处理来完成,但我怀疑可能有更好的解决方案。
我想做任务 2 的原因(将列合并为一行) 是因为我想对 result_table 执行以下操作:
select *,
(result_table.total_cost + table1.price + table.2.price) as total_combined_cost
from result_table
right join table1
right join table2
这可能要求太多,所以这里有一些关于这个问题的其他想法:
与其尝试组合多行(任务 2),不如将它们存储在临时表中 (使用 sum 计算 total_cost 会更容易)
随意抛开任何想法,不必是完整的答案,如果你有一个优雅的方式来完成任务1,我觉得它已经足够了!
==2012 年 2 月 6 日编辑/添加==
我的程序的目标是以最低的成本确定物品的最佳组合(最好同时具有更高的实用价值)。
考虑@ypercube 关于大量组的评论,临时表似乎是唯一可行的解决方案。并且还指出MySQL中没有pivoting功能(虽然it can be implemented,但没有必要进行这样的操作)。
好的,在研究了@Johan 的回答之后,我正在为任务 1 考虑这样的事情:
select * from
(
select * from
result_table
order by price asc
) as ordered_table
group by group
;
虽然看起来很狡猾,但似乎有效。
==2012 年 2 月 7 日编辑/添加==
由于可能有多个组合产生相同的最小值,因此我修改了答案:
select result_table.* from
(
select * from
(
select * from
result_table
order by price asc
) as ordered_table
group by group
) as single_min_table
inner join result_table
on result_table.group = single_min_table.group
and result_table.price = single_min_table.price
;
但是,我刚刚意识到我需要处理另一个问题:
我不能忽略所有规范,因为有一个 provider 属性,来自不同供应商的物品可能会或可能不会组装在一起,所以为了安全(并简化我的问题)我决定组合来自只有同一个提供者,所以问题变成了:
例如,如果我有一个像这样的初始表(只有 2 个组和 2 个提供者):
id group price spec provider
1 a 1 . x
2 a 2 .. y
3 a 3 ... y
4 b 1 ... y
5 b 2 x
6 b 3 z
我需要合并
id group price spec provider
1 a 1 . x
5 b 2 x
和
2 a 2 .. y
4 b 1 ... y
记录 (id 6) 可以从选择中删除,因为它没有所有可用的组。
因此不必只选择每个组的最小值,而是从每个组中选择一个,这样对于每个提供者我都有一个最小的组合成本。
【问题讨论】:
-
那么,如果你有一千个组会发生什么?您的预期结果将有 2000 列?如果你有一百万个组怎么办?
-
SQL 适用于处理多行,但将行转换为(任意数量的)列并不容易。这称为旋转。
-
作为您期望得到的结果,我可以看到您正在将行转换为列。例如:price_a,spec_a。那只是为了得到total_cost?
-
如果您添加有关附加连接的详细信息,则可能不需要旋转。