使用GROUP BY和HAVING

时间:2018-06-16 00:48:37

标签: sql oracle11g

我在mi项目中有一点问题,我正在尝试在单个表上进行查询,但我没有成功。 表是这样的:

CREATE TABLE PARTITA(
COD_SFIDA VARCHAR (20) PRIMARY KEY,
DATA_P DATE NOT NULL, 
RISULTATO CHAR (3) NOT NULL,
COD_DECK_IC VARCHAR (15),
COD_DECK_FC VARCHAR (15),
COD_EVT VARCHAR (15),
TAG_USR_IC VARCHAR (15),
TAG_USR_FC VARCHAR (15),
CONSTRAINT CHECK_RISULTATO CHECK (RISULTATO='0-0' OR RISULTATO='0-1' OR RISULTATO='1-0' OR RISULTATO='1-1'),
CONSTRAINT FK8 FOREIGN KEY (COD_DECK_IC, TAG_USR_IC) REFERENCES DECK (COD_DECK, TAG_USR) ON DELETE CASCADE,
CONSTRAINT FK17 FOREIGN KEY (COD_DECK_FC, TAG_USR_FC) REFERENCES DECK (COD_DECK, TAG_USR) ON DELETE CASCADE,
CONSTRAINT FK9 FOREIGN KEY (COD_EVT) REFERENCES TORNEO (COD_EVENTO) ON DELETE CASCADE
);

我想查看每个用户最常用的套牌。

这是我试图做的查询:

SELECT  P.COD_DECK_FC, P.TAG_USR_FC, COUNT(P.COD_DECK_FC)
FROM PARTITA P
GROUP BY P.TAG_USR_FC, P.COD_DECK_FC
UNION
SELECT  P.COD_DECK_IC, P.TAG_USR_IC, COUNT(P.COD_DECK_IC)
FROM PARTITA P
GROUP BY P.TAG_USR_IC, P.COD_DECK_IC
/

但我想查看每个用户最常用的套牌,并不是所有套牌以及用户使用它们的次数。 我该怎么办?

我希望查询显示tag_usr和每个用户使用最多的cod_deck 例如:

cod_deck         tag_usr  count(cod_deck)
-------------  ----------- --------------
1                 A1BE2      5
2                 AE3NF      6
5                 FNKJD      3

而是先前的查询返回给我:

cod_deck         tag_usr  count(cod_deck)
-------------  ----------- --------------
1                 A1BE2      5
2                 AE3NF      6
5                 FNKJD      3
2                 A1BE2      2
1                 AE3NF      3

我只是希望查询只显示用户A1BE2和AE3NF一次,因为查询必须选择每个用户最常用的套牌。

3 个答案:

答案 0 :(得分:0)

您不想选择您正在计算的字段。尝试这样的事情:

SELECT  P.COD_DECK_FC, P.TAG_USR_FC, COUNT(P.COD_SFIDA)
FROM PARTITA P
GROUP BY P.COD_DECK_FC, P.TAG_USR_FC
UNION
SELECT  P.COD_DECK_IC, P.TAG_USR_IC, COUNT(P.COD_SFIDA)
FROM PARTITA P
GROUP BY P.COD_DECK_IC, P.TAG_USR_IC

这将列出COD_DECK_FCTAG_USR_FC的所有组合  然后它在表格中显示的次数,然后对COD_DECK_ICTAG_USR_IC执行相同的操作。我不清楚你的问题究竟是什么,但我知道如果你选择它,你不应该在COUNT中添加一个字段。

答案 1 :(得分:0)

如果我正确理解,您需要subquery具有排名功能:

with t as (
       select *, row_number() over (partition by cod_deck order by count desc) Seq
       from (<union query>)
)

select *
from cte c
where seq = 1;

答案 2 :(得分:0)

我想你想要这个:

with ct as (
      select P.COD_DECK_FC as deck, P.TAG_USR_FC as usr, COUNT(P.COD_DECK_FC) as cnt
      from partita p
      group by P.TAG_USR_FC, P.COD_DECK_FC
      union all
      select  P.COD_DECK_IC, P.TAG_USR_IC, COUNT(P.COD_DECK_IC)
      from partita P
      group by P.TAG_USR_IC, P.COD_DECK_IC
     )
select ct.*
from (select ct.*, 
             row_number() over (partition by usr order by cnt desc) as seqnum
      from ct
     ) ct
where seqnum = 1;

您还可以使用grouping sets

缩短此时间
select p.*
from (select coalesce(P.COD_DECK_FC, P.COD_DECK_IC) as deck,
             coalesce(P.TAG_USR_FC, P.TAG_USR_IC) as usr, 
             count(*) as cnt,
             row_number() over (partition by coalesce(P.TAG_USR_FC, P.TAG_USR_IC) order by count(*) desc) as seqnum
      from partita p
      group by grouping sets ( (P.TAG_USR_FC, P.COD_DECK_FC), P.TAG_USR_IC, P.COD_DECK_IC) )
     ) p
where seqnum = 1;