根据最大条件排除元组

时间:2019-05-24 10:33:39

标签: sql oracle top-n

我一直试图回答以解决此SQL查询问题,但没有成功。问题如下:

问题:

为每个产品品牌

给出4个表,分别为产品维修所有者功能和“型号”显示已修复多次的故障类型。

表具有以下字段:

PRODUCTS: *Series_num, Brand, Model, Year, Code_Owner
OWNERS: *Code_Owner, Name, Surname, Street, Civic, City, (u)Phone
MALFUNCTIONS: *Malf_code, Desc
REPAIRS: *Series_num, *Malf_code, *Repair_Date, Price

* <- Primary key
(u) <- Unique attribute

在给出以下数据示例的情况下,预期结果:

| MODEL  |  BRAND   |  MALF_CODE  | NUMBER OF REPAIRS|
|----------------------------------------------------|
|   1    |  BRAND1  |      1      |        20        |
|   1    |  BRAND1  |      2      |        10        |
|   2    |  BRAND1  |      1      |         1        |
|   2    |  BRAND1  |      2      |         1        |
|   1    |  BRAND2  |      1      |        10        |
|   1    |  BRAND2  |      2      |        11        |

应该是:

| MODEL  |  BRAND   |  MALF_CODE  | NUMBER OF REPAIRS|
|----------------------------------------------------|
|   1    |  BRAND1  |      1      |        20        |
|   2    |  BRAND1  |      1      |         1        |
|   1    |  BRAND2  |      2      |        11        |

请注意,BRAND1,MODEL:2对于两种不同类型的故障具有相同的维修次数,因此可以忽略其中一行,或者可以同时显示两者(没关系)


我尝试过的内容:

要获得第一个表,我使用了一个简单的JOIN查询:

SELECT A.MODEL, A.BRAND, R.MALF_CODE, COUNT(*) AS N_REP
FROM REPAIRS R LEFT JOIN PRODUCTS A ON A.SERIES_NUM = R.SERIES_NUM
GROUP BY A.MODEL, A.BRAND, R.MALF_CODE;

然后我尝试通过 MAX()函数获得第二张表:

SELECT A.MODEL, A.BRAND, R.MALF_CODE, COUNT(*) AS N_REP
FROM REPAIRS R LEFT JOIN PRODUCTS A ON A.SERIES_NUM = R.SERIES_NUM
GROUP BY A.MODEL, A.BRAND, R.MALF_CODE
HAVING COUNT(*) IN(
    SELECT MAX(R.MALF_CODE)
    FROM REPAIRS R LEFT JOIN PRODUCTS A ON A.SERIES_NUM = R.SERIES_NUM
    GROUP BY A.MODEL, A.BRAND, R.MALF_CODE
    ORDER BY A.BRAND, R.MALF_CODE);

但这会引发以下错误:

[42000][907] ORA-00907: Missing closing Parenthesis

看来我找不到错误。 我希望我已经足够清楚了。预先感谢。

编辑:我忘了提到我知道RANK函数之类的东西,但从未听说过分区。因此,没有它们的解决方案受到高度赞赏,但不是强制性的。

1 个答案:

答案 0 :(得分:2)

如果我的理解正确,那么您希望每种型号/品牌组合的修理量最多的那一行。如果是这样,则窗口函数是一种方法:

SELECT MODEL, BRAND, MALF_CODE, N_REP
FROM (SELECT P.MODEL, P.BRAND, R.MALF_CODE, COUNT(*) AS N_REP,
             ROW_NUMBER() OVER (PARTITION BY P.MODEL, P.BRAND ORDER BY COUNT(*) DESC, R.MALF_CODE) as SEQNUM
      FROM REPAIRS R LEFT JOIN
           PRODUCTS P
           ON P.SERIES_NUM = R.SERIES_NUM
      GROUP BY P.MODEL, P.BRAND, R.MALF_CODE
     ) MB
WHERE seqnum = 1;