【问题标题】:Get ID alongside max value ORACLE SQL获取 ID 和最大值 ORACLE SQL
【发布时间】:2021-03-02 16:07:16
【问题描述】:

我目前有以下:

TABLE "QUARTO":

CREATE TABLE Quarto (
  Id                        number(2) NOT NULL, 
  LotacaoMaxima             number(1) NOT NULL, 
  TipoQuartoId              number(1) NOT NULL, 
  NumeroQuartoNumSequencial number(3) NOT NULL, 
  NumeroQuartoAndarId       varchar2(1) NOT NULL, 
  PRIMARY KEY (Id));

TABLE RESERVA:

CREATE TABLE Reserva (
  Id               number(3) NOT NULL, 
  ClienteNif       number(9) NOT NULL, 
  QuartoId         number(2) NOT NULL, 
  DataInicio       date NOT NULL, 
  DataFim          date NOT NULL, 
  NumPessoas       number(1) NOT NULL, 
  Estado           varchar2(15) NOT NULL, 
  DataCancelamento date, 
  PRIMARY KEY (Id));

我在两者中的一些数据是:

QUARTO:

| ID | LOTACAOMAXIMA | TIPOQUARTOID | NUMEROQUARTONUMSEQUENCIAL | NUMEROQUARTOANDARID |
| :--- | :--- | :--- | :--- | :--- |
| 1 | 1 | 1 | 1 | 1 |
| 2 | 1 | 1 | 2 | 1 |
| 3 | 1 | 1 | 3 | 1 |
| 4 | 1 | 1 | 4 | 1 |
| 5 | 1 | 1 | 5 | 1 |
| 6 | 1 | 1 | 6 | 1 |
| 7 | 1 | 1 | 7 | 1 |
| 8 | 1 | 1 | 8 | 1 |
| 9 | 1 | 1 | 9 | 1 |
| 10 | 1 | 1 | 10 | 1 |
| 11 | 2 | 2 | 11 | 1 |
| 12 | 2 | 2 | 12 | 1 |
| 13 | 2 | 2 | 13 | 1 |
| 14 | 2 | 2 | 14 | 1 |
| 15 | 2 | 2 | 15 | 1 |
| 16 | 2 | 2 | 16 | 1 |
| 17 | 2 | 2 | 17 | 1 |
| 18 | 2 | 2 | 18 | 1 |
| 19 | 2 | 2 | 19 | 1 |
| 20 | 2 | 2 | 20 | 1 |


RESERVA:

| ID | CLIENTENIF | QUARTOID | DATAINICIO | DATAFIM | NUMPESSOAS | ESTADO | DATACANCELAMENTO |
| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
| 1 | 296837970 | 11 | 2020-06-01 00:00:00 | 2020-06-12 00:00:00 | 1 | Finalizada | NULL |
| 2 | 275784703 | 17 | 2020-06-13 00:00:00 | 2020-06-21 00:00:00 | 1 | Finalizada | NULL |
| 3 | 220347654 | 11 | 2020-07-07 00:00:00 | 2020-07-15 00:00:00 | 2 | Finalizada | NULL |
| 4 | 294772545 | 12 | 2020-08-01 00:00:00 | 2020-08-15 00:00:00 | 2 | Finalizada | NULL |
| 5 | 220347654 | 3 | 2020-01-01 00:00:00 | 2020-01-16 00:00:00 | 1 | Finalizada | NULL |
WITH CONTAGEM_QUARTO_POR_ID AS (SELECT q.ID, COUNT(r.QUARTOID) AS NUM_RESERVAS, q.TIPOQUARTOID, q.NUMEROQUARTOANDARID
                                FROM RESERVA r
                                         INNER JOIN QUARTO q on q.ID = r.QUARTOID
                                GROUP BY q.ID, q.TIPOQUARTOID, q.NUMEROQUARTOANDARID)
SELECT t.TIPOQUARTOID, t.NUMEROQUARTOANDARID, MAX(t.NUM_RESERVAS) AS MAX
FROM CONTAGEM_QUARTO_POR_ID t
GROUP BY t.TIPOQUARTOID, t.NUMEROQUARTOANDARID

输出如下:

| TIPOQUARTOID | NUMEROQUARTOANDARID | MAX |
| :----------- | :------------------ | :-- |
| 1            |                   2 |   2 |
| 2            |                   1 |   8 |
| 1            |                   1 |   1 |

除了我目前拥有的数据之外,我还想显示每一行的脚趾 ID,但是当我将 t.ID 添加到 SELECT 时,它会强制我将其添加到 GROUP BY 并且输出是这样的:

| TIPOQUARTOID | NUMEROQUARTOANDARID | MAX | ID |
| :----------- | :------------------ | :-- | :- |
| 2            | 1                   | 2   | 11 |
| 1            | 1                   | 1   | 1  |
| 1            | 1                   | 1   | 3  |
| 1            | 2                   | 2   | 21 |
| 2            | 1                   | 1   | 17 |
| 2            | 1                   | 1   | 12 |
| 2            | 1                   | 8   | 16 |

我只想获取最大值和与该 MAX 关联的 ID。

【问题讨论】:

  • first MAX() 是一个聚合函数,这意味着如果 select 子句有其他非聚合列,则需要使用带有 overgroup by 的那些。请查看msdn 以获得更好的信息。
  • 第二件事是请提供表模式,也许还有一些示例数据等,这对这个过程有很大帮​​助。
  • @T.Peter 将添加表模式和我目前拥有的数据

标签: sql oracle group-by aggregate-functions analytic-functions


【解决方案1】:

我不建议使用两个级别的聚合。只需使用窗口功能:

WITH CONTAGEM_QUARTO_POR_ID AS (
      SELECT q.ID, COUNT(*) AS NUM_RESERVAS, q.TIPOQUARTOID, q.NUMEROQUARTOANDARID,
             ROW_NUMBER() OVER (PARTITION BY q.TIPOQUARTOID, q.NUMEROQUARTOANDARID ORDER BY COUNT(*) DESC) as seqnum
      FROM RESERVA r INNER JOIN
           QUARTO q 
           ON q.ID = r.QUARTOID
      GROUP BY q.ID, q.TIPOQUARTOID, q.NUMEROQUARTOANDARID
     )
SELECT cq.*
FROM CONTAGEM_QUARTO_POR_ID cq
WHERE seqnum = 1;

我认为这比两个聚合的性能略好(但值得检查)。

这种方法的一个优点是它更灵活。如果您想要平局,只需将子查询中的ROW_NUMBER() 更改为RANK()

也许更重要的是,ROW_NUMBER() 是 SQL 中的一个“惯用语”,用于每组返回一行(或特定数量的行)。学习如何使用它非常有价值。

【讨论】:

    【解决方案2】:

    您需要NUM_RESERVASPARTITION BY TIPOQUARTOID, NUMEROQUARTOANDARID 列的MAX() OVER () 分析函数,以便按列表为分区内的这些列提供分组,例如

    WITH CONTAGEM_QUARTO_POR_ID AS
    (
      SELECT q.ID,
             COUNT(r.QUARTOID) AS NUM_RESERVAS,
             q.TIPOQUARTOID,
             q.NUMEROQUARTOANDARID
        FROM RESERVA r
        JOIN QUARTO q
          on q.ID = r.QUARTOID
       GROUP BY q.ID, q.TIPOQUARTOID, q.NUMEROQUARTOANDARID
    ), t AS
    (
     SELECT t.TIPOQUARTOID, t.NUMEROQUARTOANDARID, t.NUM_RESERVAS, 
            MAX(t.NUM_RESERVAS) 
            OVER (PARTITION BY t.TIPOQUARTOID, t.NUMEROQUARTOANDARID) AS MAX, 
            t.ID
       FROM CONTAGEM_QUARTO_POR_ID t
    )
    SELECT TIPOQUARTOID, NUMEROQUARTOANDARID, NUM_RESERVAS, ID
      FROM t
     WHERE NUM_RESERVAS = MAX
    

    或者更直接地使用HAVING子句

    SELECT q.TIPOQUARTOID,
           q.NUMEROQUARTOANDARID,
           COUNT(r.QUARTOID) AS NUM_RESERVAS,
           q.ID
      FROM RESERVA r
      JOIN QUARTO q
        on q.ID = r.QUARTOID
     GROUP BY q.ID, q.TIPOQUARTOID, q.NUMEROQUARTOANDARID
     HAVING COUNT(r.QUARTOID) = q.TIPOQUARTOID
    

    【讨论】:

      【解决方案3】:

      您可以在查询中使用KEEP 子句,而无需进行太多更改,如下所示:

      WITH CONTAGEM_QUARTO_POR_ID AS 
        (SELECT q.ID, COUNT(r.QUARTOID) AS NUM_RESERVAS, q.TIPOQUARTOID, q.NUMEROQUARTOANDARID
           FROM RESERVA r
           INNER JOIN QUARTO q on q.ID = r.QUARTOID
         GROUP BY q.ID, q.TIPOQUARTOID, q.NUMEROQUARTOANDARID)
      SELECT t.TIPOQUARTOID, t.NUMEROQUARTOANDARID, MAX(t.NUM_RESERVAS) AS MAX, 
             max(t.ID) keep(dense_rank first order by t.NUM_RESERVAS desc nulls last) as ID -- this
      FROM CONTAGEM_QUARTO_POR_ID t
      GROUP BY t.TIPOQUARTOID, t.NUMEROQUARTOANDARID
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-04-16
        • 1970-01-01
        • 1970-01-01
        • 2016-04-14
        • 1970-01-01
        • 1970-01-01
        • 2019-07-13
        相关资源
        最近更新 更多