我有一个非常基本的数据库,用于跟踪 6 个不同事件的分数。每个事件包含 4 个事件。
我的当前 SQL 查询非常基本,看起来与下面的非常相似;
Select Name,
SUM(ISNULL(p.e1_e1_points, 0)+ISNULL(p.e1_e2_points, 0)+ISNULL(p.e1_e3_points, 0)+ISNULL(p.e1_e4_points, 0)) AS Event1,
SUM(ISNULL(p.e2_e1_points, 0)+ISNULL(p.e2_e2_points, 0)+ISNULL(p.e2_e3_points, 0)+ISNULL(p.e2_e4_points, 0)) AS Event2,
SUM(ISNULL(p.e3_e1_points, 0)+ISNULL(p.e3_e2_points, 0)+ISNULL(p.e3_e3_points, 0)+ISNULL(p.e3_e4_points, 0)) AS Event3,
SUM(ISNULL(p.e4_e1_points, 0)+ISNULL(p.e4_e2_points, 0)+ISNULL(p.e4_e3_points, 0)+ISNULL(p.e4_e4_points, 0)) AS Event4,
SUM(ISNULL(p.e5_e1_points, 0)+ISNULL(p.e5_e2_points, 0)+ISNULL(p.e5_e3_points, 0)+ISNULL(p.e5_e4_points, 0)) AS Event5,
SUM(ISNULL(p.e6_e1_points, 0)+ISNULL(p.e6_e2_points, 0)+ISNULL(p.e6_e3_points, 0)+ISNULL(p.e6_e4_points, 0)) AS Event6
from points
Run Code Online (Sandbox Code Playgroud)
我需要能够添加一个额外的列,它是列(事件 1、事件 2、事件 3 等)中的最小值。
And*_*y M 14
基本上,这是关于寻找行式最小值。
在这个 Stack Overflow 问题的最受好评的答案中有一个优雅的内联解决方案:
根据该解决方案,如果您有这样的表格T:
C1 C2 C3
-- -- --
… … …
… … …
Run Code Online (Sandbox Code Playgroud)
您可以找到这样的逐行最小值:
SELECT
C1,
C2,
C3,
(
SELECT MIN(C)
FROM (VALUES (C1), (C2), (C3) AS v (C)
) AS MinC
FROM
T
;
Run Code Online (Sandbox Code Playgroud)
基本上你是安排的价值观C1,C2,C3为一列,并正在申请一个正常的(逐列)聚合函数,以它来寻找最小。
现在在你的情况下C1,C2等是表达式。通常这很好,您可以将VALUES行构造函数与表达式一起使用。但是在这种情况下,每个表达式都已经包含一个聚合函数 ( SUM()),这阻止了我们直接应用该方法(VALUES表达式不能使用聚合函数)。
不过,这个问题很容易解决。您可以将当前查询用作派生表或 CTE,并在外部级别应用该方法,其中表达式只是引用,如下所示:
SELECT
Name,
Event1,
Event2,
Event3,
Event4,
Event5,
Event6,
(
SELECT MIN(Event)
FROM (VALUES (Event1), (Event2), (Event3), (Event4), (Event5), (Event6)) AS v (Event)
) AS MinEvent
FROM
(
SELECT
... /* your current query */
) AS derived
;
Run Code Online (Sandbox Code Playgroud)
这是一个相同的解决方案,但使用 CTE:
WITH cte AS
(
SELECT
... /* your current query */
)
SELECT
Name,
Event1,
Event2,
Event3,
Event4,
Event5,
Event6,
(
SELECT MIN(Event)
FROM (VALUES (Event1), (Event2), (Event3), (Event4), (Event5), (Event6)) AS v (Event)
) AS MinEvent
FROM
cte
;
Run Code Online (Sandbox Code Playgroud)
我已经设置了一个 dbfiddle 示例来模拟您的数据:
Run Code Online (Sandbox Code Playgroud)create table events (name varchar(20), event1 int, event2 int, event3 int, event4 int); insert into events values ('name1',10,11,12,13),('name2',20,21,22,23),('name3',30,31,32,33); GO3 行受影响
恕我直言,你有一些选择:
嵌套IIF
Run Code Online (Sandbox Code Playgroud)-- this is your query with a as ( select name, event1, event2, event3, event4 from events ) select name, event1, event2, event3, event4, iif (event1 < event2, event1, iif(event2 < event3, event2, iif(event3 < event4, event3, event4))) min_event from a; GO名称 | 事件1 | 事件2 | 事件3 | 事件4 | 最小事件 :---- | -----: | -----: | -----: | -----: | --------: 名称1 | 10 | 10 11 | 11 12 | 12 13 | 10 名称2 | 20 | 21 | 21 22 | 22 23 | 23 20 名称3 | 30| 31 | 32 | 32 33 | 33 30
取消透视
您可以使用 UNPIVOT 解决方案以这种方式获取最小值:
Run Code Online (Sandbox Code Playgroud)with a as ( select name, event1, event2, event3, event4 from events ) , b as ( select name, min(event) as min_event from a unpivot (event for n in([event1],[event2],[event3],[event4])) upv group by name ) select a.name, a.event1, a.event2, a.event3, a.event4, b.min_event from a join b on b.name = a.name GO名称 | 事件1 | 事件2 | 事件3 | 事件4 | 最小事件 :---- | -----: | -----: | -----: | -----: | --------: 名称1 | 10 | 10 11 | 11 12 | 12 13 | 10 名称2 | 20 | 21 | 21 22 | 22 23 | 23 20 名称3 | 30| 31 | 32 | 32 33 | 33 30
dbfiddle在这里
| 归档时间: |
|
| 查看次数: |
58456 次 |
| 最近记录: |