我正在尝试根据PL / SQL过程中的一个特定字段聚合数据。我有这张桌子,我们称之为MYTABLE:
我想获得以下内容:
列c的值只能出现一次, 列d的值必须与b = 1和c = 1111的行的d值相同, 列e的值必须填充c的两条相等线的列e的最小值(最小值在1111的0和-1之间)
谢谢, ILARIA
答案 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;
。
MAX
和KEEP
/ 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
通过这种方式,FIRST
和LAST
可让我们对各行进行比较,并更好地控制聚合返回的内容。
我希望这会有所帮助。