SQL组函数嵌套得太深了

时间:2013-11-17 19:40:20

标签: sql oracle aggregate-functions

我想创建一个SQL查询,查找pname中重复次数最少的部分supplier_parts_shipment

表1供应商(sno,sname,city)

1, ahmad, jeddah
2,kaled,med
3,njwa,med

表2部分(pno,pname,color)

1, laptop, red
2,keybord,blue

表3 supplier_parts_shipment(shno,sno,pno,date)

1,1,1,2014
2,2,1,2014
3,3,2,2014

我试过这样的事情:

  SELECT pname 
       , min(count(pno)) 
    FROM parts 
   WHERE pno IN (SELECT pno 
                   FROM supplier_parts_shipment 
                  group by 
                        pname 
                 HAVING min(count(pno))
                )
SQL> /
pno IN(SELECT pno FROM supplier_parts_shipment group by pname HAVING min(count(pno))))
                                                                         *
ERROR at line 2:
ORA-00935: group function is nested too deeply

4 个答案:

答案 0 :(得分:0)

min(count(pno)) 

毫无意义。这就是你得到错误的原因。尝试:

select parts.pname
     , subse.c 
  from (select pno
             , dense_rank() over (order by c asc) r
             , c
          from (select pno
                     , count(pno) as c
                  from supplier_parts_shipment
                 group by
                       pno
               )
       ) subse
 inner join parts
    on (parts.pno = subse.pno)
 where subse.r = 1

最里面的选择计数pno的supplier_parts_shipment,第二个级别找到最里面的pno数量最少的pno。最外面的select然后将pname从parts和filters连接到重复次数最少的那个。

答案 1 :(得分:0)

我会以不同的方式解决这个问题。

首先创建一个查询,以pname的形式显示按升序值排序的货件计数。将其用作子查询并选择第一个。

SELECT * FROM (
    SELECT COUNT(sps.pno), p.pname 
    FROM supplier_parts_shipment sps
    JOIN parts p on sps.pno = p.pno
    GROUP BY pname
    ORDER BY COUNT(sps.pno) ASC)
WHERE ROWNUM = 1

答案 2 :(得分:0)

如果有多个部分的频率最低,而你想要所有这些部分:

WITH pno_frequencies AS (
  SELECT pno,
         COUNT(1) AS pno_cnt
  FROM   supplier_parts_shipment
  GROUP BY pno
),
least_frequent_pnos AS (
  SELECT pno
  FROM   pno_frequencies
  WHERE  pno_cnt = ( SELECT MIN( pno_cnt ) FROM pno_frequencies )
)
SELECT pname
FROM   parts p
WHERE  EXISTS (SELECT 1
               FROM   least_frequent_pnos f
               WHERE  p.pno = f.pno
              );

如果您只需要一个零件,无论是否有多个零件具有相同的最小频率,那么:

WITH pno_frequencies AS (
  SELECT pno,
         COUNT(1) AS pno_cnt
  FROM   supplier_parts_shipment
  GROUP BY pno
  ORDER BY pno_cnt ASC
),
least_frequent_pno AS (
  SELECT pno
  FROM   pno_frequencies
  WHERE  ROWNUM = 1
)
SELECT pname
FROM   parts p
WHERE  EXISTS (SELECT 1
               FROM   least_frequent_pno f
               WHERE  p.pno = f.pno
              );

SQLFIDDLE

答案 3 :(得分:0)

如果您使用的是 oracle 12c 或更高版本,则使用row limiting clause会很容易,如下所示:

Select p.pname, count(1) as cnt
From parts p
Join supplier_parts_shipment sps
  On sps.pno = p.pno
Group by p.name
Order by cnt
Fetch first row with ties

有关行限制子句的更多信息,请参见this document

干杯!