我需要为A列的每一行选择具有B列最小值的行,但它应与到目前为止为A列选择的其他值不同。因此,A的顺序很重要。同样,如果B用完了,什么也没留下,那么A的后面的值应该为NULL或不出现在结果中。
A和B均为数字(或时间戳)。 例如:
A | B |
----+---+
1 | 3 |
1 | 5 |
1 | 6 |
2 | 3 |
2 | 5 |
9 | 3 |
9 | 5 |
所以期望的结果是:
A | B |
----+---+
1 | 3 |
2 | 5 |
select A, min(B) group by A
显然不起作用,因为我不想重复B。 Distinct
也行不通,因为行已经不同。我真的在任何地方都找不到类似的问题。
我正在使用的实际数据是redshift上的时间序列数据库,因此A和B是时间戳。特别欢迎CTE。
答案 0 :(得分:0)
首先,我认为可以使用ROW_NUMBER () OVER (ORDER PARTITION BY B DESC)
解决此问题,但是存在一个问题,B中的数字不应重复。
目前唯一想到的是创建临时表,我知道这不是最好的方法,但是您可以改进它
DECLARE @Tabla1 TABLE(A INT)
DECLARE @Tabla2 TABLE(B INT)
DECLARE @Tabla3 TABLE(A INT, B INT)
INSERT INTO @Tabla1 SELECT DISTINCT A FROM PRUEBA
WHILE (SELECT COUNT(*) FROM @Tabla1) > 0
BEGIN
DECLARE @A INT, @B INT;
SET @A = (SELECT TOP 1 * FROM @Tabla1);
SET @B = (SELECT MIN(B) FROM PRUEBA WHERE A = @A AND B NOT IN(SELECT * FROM @Tabla2));
INSERT INTO @Tabla2 VALUES (@B)
DELETE FROM @Tabla1 WHERE A = @A
INSERT INTO @Tabla3 SELECT A, B FROM PRUEBA WHERE A = @A AND B = @B
END
SELECT * FROM @Tabla3
也许您可以使用游标,但是必须计算一下,这会花费更多的计算开销,例如游标或临时表
答案 1 :(得分:0)
这基本上是“查找对角线”的问题。您需要知道A中B的等级以及所有A中的等级。我相信这适用于给出的数据:
select A, B from (
select row_number() over (partition by A order by B) as RN,
dense_rank() over (order by A) as DR.
A, B
from <table> )
where RN = DR;
对于更复杂的情况,此解决方案将变得更加复杂。
附录: 因为我知道会被问到这是一个有趣的问题,所以我弄清楚了这样一个更复杂的解决方案是什么样的:
select min(A) as A, B from (
select decode(A <> nvl(min(A) over (order by DRB, DRA rows between unbounded preceding and 1 preceding),-1), true, 'good', 'no good') as Y,
A, B from (
select dense_rank() over (partition by B order by A) as DRA,
dense_rank() over ( order by B) as DRB,
A, B from <table>
)
where DRA <= DRB
)
where Y = 'good'
group by B
order by A, B;