我需要在 SQL 中进行高级选择,但我陷入困境。
我有下表:
id | user_id | position | value
1 | 1 | 1 | 1
1 | 1 | 2 | 1
1 | 1 | 3 | 3
1 | 2 | 1 | 2
1 | 2 | 2 | 2
1 | 2 | 3 | 2
1 | 3 | 1 | 3
1 | 3 | 2 | 2
1 | 3 | 3 | 1
我需要一个查询,为我提供一个按如下顺序排序的结果集:
- 每个用户的总金额(用户 1: 5、用户 2: 6、用户 3: 6)
- 每个用户的位置 3 的值(用户 1: 3、用户 2: 2、用户 3: 1)
- 每个用户的 pos 3 的 val + pos 2 的 val(用户 1: 4、用户 2: 4、用户 3: 4)
- 每个用户的 pos 3 的 val + pos 2 的 val + pos 1 的 val(用户 1: 5、用户 2: 6、用户 3: 6)
这只是一个示例,表实际上可以包含更多位置,因此我需要一个不在三个位置上硬编码的查询。
注意:每个 user_id 的位置数始终相同。在本示例中为三个,但我也可以截断表并使用五个位置为每个用户添加数据。
一个丑陋的解决方案是假设位置永远不会超过十个,创建 pos1、pos2 等作为列,然后将它们相应地添加到查询中。如果您只使用三个位置,您会得到很多 NULL 值,并且您还会陷入最多十个位置的困境。
我考虑过使用临时表,但也没有找到突破口。
你会怎么做?
最佳答案
I need a query that is not hard coded on three positions.
那么您就无法在列中输出小计。 SQL 要求在准备查询时固定列;您无法编写动态附加更多列的查询,因为它会发现数据中有多少个不同的值。
但是,您可以输出动态数量的行。
SELECT t1.user_id, CONCAT(t1.position, '-', MAX(t2.position)) AS position_range,
SUM(t2.value) AS subtotal
FROM MyTable t1
INNER JOIN MyTable t2
ON t1.user_id = t2.user_id AND t1.position <= t2.position
GROUP BY t1.user_id, t1.position;
输出为:
+---------+----------------+----------+
| user_id | position_range | subtotal |
+---------+----------------+----------+
| 1 | 1-3 | 5 |
| 1 | 2-3 | 4 |
| 1 | 3-3 | 3 |
| 2 | 1-3 | 6 |
| 2 | 2-3 | 4 |
| 2 | 3-3 | 2 |
| 3 | 1-3 | 6 |
| 3 | 2-3 | 3 |
| 3 | 3-3 | 1 |
+---------+----------------+----------+
在获取整个结果集后,您必须编写应用程序代码才能将其转换为列。
抱歉,在任何品牌的 RDBMS 中都无法编写完全动态的数据透视查询。您有两个选择:
编写代码以根据数据生成 SQL,如 @TimLehner 的更新答案所示
编写代码来后处理通用查询,如我上面所示的查询。
关于mysql - 非常高级的 sql 查询的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15929926/