如何基于列中的一个重复值进行聚合

时间:2017-03-12 16:28:15

标签: sql oracle aggregate

我正在尝试根据PL / SQL过程中的一个特定字段聚合数据。我有这张桌子,我们称之为MYTABLE:

enter image description here

我想获得以下内容:

DESIRED RESULT

列c的值只能出现一次, 列d的值必须与b = 1和c = 1111的行的d值相同, 列e的值必须填充c的两条相等线的列e的最小值(最小值在1111的0和-1之间)

谢谢, ILARIA

1 个答案:

答案 0 :(得分:0)

这不需要PL / SQL。您可以在SQL中进行聚合。

设置数据后:

CREATE TABLE MYTABLE (
  A NUMBER,
  B NUMBER,
  C NUMBER,
  D NUMBER,
  E NUMBER
);

INSERT INTO MYTABLE VALUES (111, 0, 1111, 11, 0);
INSERT INTO MYTABLE VALUES (222, 1, 2222, 22, 1);
INSERT INTO MYTABLE VALUES (222, 1, 1111, 22, 1);
INSERT INTO MYTABLE VALUES (222, 1, 3333, 22, 1);
COMMIT;

我们可以首先选择C的DISTINCT值,但GROUP BY C:

SQL> SELECT C
  2  FROM MYTABLE
  3  GROUP BY C;

2222  
1111  
3333  

然后,要为E的每个不同值获取C的最低值,我们必须将聚合函数应用于E,因此每个唯一值{{返回的值只返回一个值1}}:

C

请注意,这与您提供的示例表不一致,但应符合您描述的目标:

  

"列e的值必须填充最小值   列e表示c"

中的两条相等线

然后要包含SQL> SELECT C, MIN(E) AS E 2 FROM MYTABLE 3 GROUP BY C 4 ORDER BY C ASC, E ASC; 1111 0 2222 1 3333 1 ,我们将再次需要一个聚合函数(除了D之外,每个列都是这种情况,因为每个非{1}都需要返回一个唯一值。在这种情况下,值不是简单的C / C,但也依赖于MIN的值。在这种情况下,我建议{{1}在您的聚合函数中。以下内容适用于您提供的示例,但您可能需要更改条件以实现目标:

MAX

将上述内容与此替代方案进行比较,可以看到正在考虑B的值:

KEEP

然后,要完成查询,请将汇总函数应用于SQL> SELECT C, 2 MIN(D) KEEP (DENSE_RANK LAST ORDER BY B ASC) AS D, 3 MIN(E) AS E 4 FROM MYTABLE 5 GROUP BY C 6 ORDER BY C ASC, D ASC, E ASC; 1111 22 0 2222 22 1 3333 22 1 B。您没有指定要压缩它们的方式,所以我只是使用SQL> SELECT C, 2 MIN(D) KEEP (DENSE_RANK LAST ORDER BY B DESC) AS D, 3 MIN(E) AS E 4 FROM MYTABLE 5 GROUP BY C 6 ORDER BY C ASC, D ASC, E ASC; 1111 11 0 2222 22 1 3333 22 1 作为占位符,恰好使用了您的数据。

A

编辑:有关B / MIN的进一步讨论:

以下是说明SQL> SELECT 2 MIN(A) AS A, 3 MIN(B) AS B, 4 C AS C, 5 MIN(D) KEEP (DENSE_RANK LAST ORDER BY B ASC) AS D, 6 MIN(E) AS E 7 FROM MYTABLE 8 GROUP BY C 9 ORDER BY C ASC, A ASC, B ASC, D ASC, E ASC; 111 0 1111 22 0 222 1 2222 22 1 222 1 3333 22 1 和排名的示例 有很多可以探索的内容,documentation可能很有用。

为了探索KEEP正在做什么,我将切换到电影的一般例子。假设您有下表。它包括电影制片厂,他们制作的电影片头,以及他们的利润和人们喜欢它们的数量:

FIRST

福克斯'和#Orion'在此示例中多次出现在数据中。 如果我们愿意,我们可以通过标准聚合为每个工作室的单个电影找到最大的利润:

LAST

但是,这实际上并没有告诉我们哪部电影赚的最多钱。我们可以尝试在标题上采用MIN或MAX,但这不会有帮助,因为KEEP电影可能没有赚到最多钱;它们位于不同的列中 - 它们是独立的。所以我们可以CREATE TABLE MOVIE( MOVIE_TITLE VARCHAR2(200) NOT NULL PRIMARY KEY, DISTRIBUTOR VARCHAR2(200) NOT NULL, MONEY_MADE NUMBER(15,2) NOT NULL, REVIEW_SCORE NUMBER(3,0) NOT NULL ); INSERT INTO MOVIE VALUES ('Avatar','Fox',2787965087,83); INSERT INTO MOVIE VALUES ('Aliens','Fox',183000000,98); --Not true moned-made, but just pretend INSERT INTO MOVIE VALUES ('Prometheus','Fox',2787965087,72); INSERT INTO MOVIE VALUES ('Terminator','Orion',78000000,100); INSERT INTO MOVIE VALUES ('RoboCop','Orion',53000000,88); COMMIT; 制作赚钱最多的电影。 "事实"普罗米修斯和阿凡达在这里赚了同样多的钱:

SQL> SELECT DISTRIBUTOR, MAX(MONEY_MADE) FROM MOVIE
  2  GROUP BY DISTRIBUTOR;
DISTRIBUTOR  MAX(MONEY_MADE)  
Orion        78000000         
Fox          2787965087       

这说:"对于每个电影工作室,去获取赚钱最多的电影,如果有结合,只需获得MAX(字母)所以我只有一行& #34;
MAXKEEP / SELECT DISTRIBUTOR, MAX(MOVIE_TITLE) KEEP (DENSE_RANK LAST ORDER BY MONEY_MADE ASC) AS MOVIE_TITLE FROM MOVIE GROUP BY DISTRIBUTOR; DISTRIBUTOR MOVIE_TITLE Fox Prometheus Orion Terminator 是我们获得每个工作室收入最高的电影的原因。 DENSE_RANK进来说" 通过他们的MONEY_MADE为每个工作室的电影排名,并且只保留最后一个(最赚钱的)"。由于我们在“阿凡达”和“普罗米修斯”之间有一个平局,FIRST将返回这两个,然后LAST有助于解决平局(按字母顺序排列)。

如果我切换到KEEP,我会获得“阿凡达”,因为它按字母顺序排在第一位:

KEEP

如果我MAX MIN而不是SELECT DISTRIBUTOR, MIN(MOVIE_TITLE) KEEP (DENSE_RANK LAST ORDER BY MONEY_MADE ASC) AS MOVIE_TITLE FROM MOVIE GROUP BY DISTRIBUTOR; DISTRIBUTOR MOVIE_TITLE Fox Avatar Orion Terminator ,我将获得每个工作室最低钱的费用:

KEEP

通过这种方式,FIRSTLAST可让我们对各行进行比较,并更好地控制聚合返回的内容。

我希望这会有所帮助。