将按类别过滤的最高绝对值插入另一个 table
Insert highest absolut value filtered by category into another table
我想 select 每个类别的 table 中的最高绝对值。
这是我的 table:
CREATE TABLE mytable
(
CategoryID INTEGER NOT NULL PRIMARY KEY,
ExpValue INTEGER NOT NULL
);
INSERT INTO mytable (CategoryID, ExpValue) VALUES (11, 0);
INSERT INTO mytable (CategoryID, ExpValue) VALUES (11, 11);
INSERT INTO mytable (CategoryID, ExpValue) VALUES (11, -59);
INSERT INTO mytable (CategoryID, ExpValue) VALUES (130, 0);
INSERT INTO mytable (CategoryID, ExpValue) VALUES (130, 59);
INSERT INTO mytable (CategoryID, ExpValue) VALUES (130, -2);
这就变成了这个
+------------+----------+
| CategoryID | ExpValue |
+------------+----------+
| 11 | 0 |
| 11 | -13 |
| 11 | -59 |
| 130 | 0 |
| 130 | 59 |
| 130 | 2 |
+------------+----------+
对于每个类别,我 select 最高值是这样的:
INSERT INTO #Result
SELECT TOP 1 *
FROM #SmallTable
WHERE CategoryID = 11
ORDER BY ExpValue DESC;
这个效果很好。但我知道发现了一个边缘案例。如您所见,对于 CategoryID = 11
,它将 return 为 0 的行。
但我希望它改为选择值 -59。因此,任何数字中最高的 abs()
。
而对于 CategoryID = 130
,它应该连续选择 59。
table只能有3种情况。
对于存在多个正值和一个 0 值的特定 CategoryID
-> return 最高值
对于存在多个 0 值的特定 CategoryID
-> 选择一个 0 值
对于存在多个负值和一个 0 值的特定 CategoryID
-> 选择最小值。
如您所见,总是存在 0 的回退,但除了唯一的正值、负值或根本没有其他值。
table 实际上有更多的列 (30),但我只显示了查询所需的 2 列。但实际上我需要整行。
我的示例 table 的结果应该是:
+------------+----------+
| CategoryID | ExpValue |
+------------+----------+
| 11 | -59 |
| 130 | 59 |
+------------+----------+
编辑:谢谢大家。我最终是这样做的:
INSERT INTO #Result
SELECT TOP 1 *
FROM #SmallTable
WHERE CategoryID = 11
ORDER BY ABS(ExpValue) DESC;
您可以对 amx abs(
使用子查询
select m.CategoryID, m.ExpValue
from #SmallTable m
INNER JOIN (
Select CategoryID , max(abs(ExpValue )) max_abs
FROM #SmallTable
GROUP BY CategoryID
) t on t.max_abs = abs(ExpValue )
and t.CategoryID = m.CategoryID
.
INSERT INTO #Result
select m.CategoryID, m.ExpValue
from #SmallTable m
INNER JOIN (
Select CategoryID , max(abs(ExpValue )) max_abs
FROM #SmallTable
GROUP BY CategoryID
) t on t.max_abs = abs(ExpValue )
and t.CategoryID = m.CategoryID
您可以使用单个聚合和一些条件逻辑:
select categoryid,
(case when abs(min(expval)) > abs(max(expval)) then min(expval)
else max(expval)
end)
from #smalltable
group by categoryid;
如果您只想要一个类别,您可以在 group by
.
之前进行过滤
另一种选择。在 ORDER BY
子句中使用 ROW_NUMBER
窗口函数,以及 TOP (1) WITH TIES
:
SELECT TOP (1) WITH TIES
CategoryID,
ExpValue
FROM
mytable
ORDER BY ROW_NUMBER() OVER (PARTITION BY CategoryID ORDER BY ABS(ExpValue) DESC);
结果:
+------------+----------+
| CategoryID | ExpValue |
+------------+----------+
| 11 | -59 |
| 130 | 59 |
+------------+----------+
通过将行号放入 select 列表中可以更容易地了解它是如何工作的:
CategoryID,
ExpValue,
ROW_NUMBER() OVER (PARTITION BY CategoryID ORDER BY ABS(ExpValue) DESC) as RowNum
FROM
mytable;
结果:
+------------+----------+--------+
| CategoryID | ExpValue | RowNum |
+------------+----------+--------+
| 11 | -59 | 1 |
| 11 | 11 | 2 |
| 11 | 0 | 3 |
| 130 | 59 | 1 |
| 130 | -2 | 2 |
| 130 | 0 | 3 |
+------------+----------+--------+
TOP (1) WITH TIES
只取每个分组中的第 1 行。
这里是 Rextester Demo。
我想 select 每个类别的 table 中的最高绝对值。
这是我的 table:
CREATE TABLE mytable
(
CategoryID INTEGER NOT NULL PRIMARY KEY,
ExpValue INTEGER NOT NULL
);
INSERT INTO mytable (CategoryID, ExpValue) VALUES (11, 0);
INSERT INTO mytable (CategoryID, ExpValue) VALUES (11, 11);
INSERT INTO mytable (CategoryID, ExpValue) VALUES (11, -59);
INSERT INTO mytable (CategoryID, ExpValue) VALUES (130, 0);
INSERT INTO mytable (CategoryID, ExpValue) VALUES (130, 59);
INSERT INTO mytable (CategoryID, ExpValue) VALUES (130, -2);
这就变成了这个
+------------+----------+
| CategoryID | ExpValue |
+------------+----------+
| 11 | 0 |
| 11 | -13 |
| 11 | -59 |
| 130 | 0 |
| 130 | 59 |
| 130 | 2 |
+------------+----------+
对于每个类别,我 select 最高值是这样的:
INSERT INTO #Result
SELECT TOP 1 *
FROM #SmallTable
WHERE CategoryID = 11
ORDER BY ExpValue DESC;
这个效果很好。但我知道发现了一个边缘案例。如您所见,对于 CategoryID = 11
,它将 return 为 0 的行。
但我希望它改为选择值 -59。因此,任何数字中最高的 abs()
。
而对于 CategoryID = 130
,它应该连续选择 59。
table只能有3种情况。
对于存在多个正值和一个 0 值的特定
CategoryID
-> return 最高值对于存在多个 0 值的特定
CategoryID
-> 选择一个 0 值对于存在多个负值和一个 0 值的特定
CategoryID
-> 选择最小值。
如您所见,总是存在 0 的回退,但除了唯一的正值、负值或根本没有其他值。
table 实际上有更多的列 (30),但我只显示了查询所需的 2 列。但实际上我需要整行。
我的示例 table 的结果应该是:
+------------+----------+
| CategoryID | ExpValue |
+------------+----------+
| 11 | -59 |
| 130 | 59 |
+------------+----------+
编辑:谢谢大家。我最终是这样做的:
INSERT INTO #Result
SELECT TOP 1 *
FROM #SmallTable
WHERE CategoryID = 11
ORDER BY ABS(ExpValue) DESC;
您可以对 amx abs(
使用子查询select m.CategoryID, m.ExpValue
from #SmallTable m
INNER JOIN (
Select CategoryID , max(abs(ExpValue )) max_abs
FROM #SmallTable
GROUP BY CategoryID
) t on t.max_abs = abs(ExpValue )
and t.CategoryID = m.CategoryID
.
INSERT INTO #Result
select m.CategoryID, m.ExpValue
from #SmallTable m
INNER JOIN (
Select CategoryID , max(abs(ExpValue )) max_abs
FROM #SmallTable
GROUP BY CategoryID
) t on t.max_abs = abs(ExpValue )
and t.CategoryID = m.CategoryID
您可以使用单个聚合和一些条件逻辑:
select categoryid,
(case when abs(min(expval)) > abs(max(expval)) then min(expval)
else max(expval)
end)
from #smalltable
group by categoryid;
如果您只想要一个类别,您可以在 group by
.
另一种选择。在 ORDER BY
子句中使用 ROW_NUMBER
窗口函数,以及 TOP (1) WITH TIES
:
SELECT TOP (1) WITH TIES
CategoryID,
ExpValue
FROM
mytable
ORDER BY ROW_NUMBER() OVER (PARTITION BY CategoryID ORDER BY ABS(ExpValue) DESC);
结果:
+------------+----------+
| CategoryID | ExpValue |
+------------+----------+
| 11 | -59 |
| 130 | 59 |
+------------+----------+
通过将行号放入 select 列表中可以更容易地了解它是如何工作的:
CategoryID,
ExpValue,
ROW_NUMBER() OVER (PARTITION BY CategoryID ORDER BY ABS(ExpValue) DESC) as RowNum
FROM
mytable;
结果:
+------------+----------+--------+
| CategoryID | ExpValue | RowNum |
+------------+----------+--------+
| 11 | -59 | 1 |
| 11 | 11 | 2 |
| 11 | 0 | 3 |
| 130 | 59 | 1 |
| 130 | -2 | 2 |
| 130 | 0 | 3 |
+------------+----------+--------+
TOP (1) WITH TIES
只取每个分组中的第 1 行。
这里是 Rextester Demo。