簡體   English   中英

在 Firebird 中選擇最接近的最大值

[英]Select closest maximal numeric value in Firebird

假設有 2 個表,我們稱它們為“Master”和“Detail”:

Master
--------------------------------
| ID | field_1 | ... | field_n |
--------------------------------
Detail
--------------------------------------------
| ID | master_id | f_value | ... | field_n |
--------------------------------------------
| 1  |      1    |   0.03  | ... |   ...   |
--------------------------------------------
| 2  |      1    |   0.95  | ... |   ...   |
--------------------------------------------
| 3  |      1    |   1.22  | ... |   ...   |
--------------------------------------------
| 4  |      2    |   0.91  | ... |   ...   |
--------------------------------------------
| 5  |      2    |   0.93  | ... |   ...   |
--------------------------------------------
| 6  |      2    |   2.07  | ... |   ...   |
--------------------------------------------

有 2 個輸入參數:主 ID 列表( master_id_list )和數值( num_value )。

對於master_id_list每個ID ,我應該得到一個 Detail 記錄:

  1. 如果num_value < MIN( f_value ) ,它應該是MIN( f_value )的記錄
  2. 如果num_value > MAX( f_value ) ,它應該是MAX( f_value )的記錄
  3. 否則它應該是最接近最大f_value的記錄

例一。 master_id_list = [ 1, 2 ]num_value = 0 結果:

--------------------------------------------
| 1  |      1    |   0.03  | ... |   ...   |
--------------------------------------------
| 4  |      2    |   0.91  | ... |   ...   |
--------------------------------------------

例2。 master_id_list = [ 1, 2 ]num_value = 50 結果:

--------------------------------------------
| 3  |      1    |   1.22  | ... |   ...   |
--------------------------------------------
| 6  |      2    |   2.07  | ... |   ...   |
--------------------------------------------

例3。 master_id_list = [ 1, 2 ]num_value = 0.94 結果:

--------------------------------------------
| 2  |      1    |   0.95  | ... |   ...   |
--------------------------------------------
| 6  |      2    |   2.07  | ... |   ...   |
--------------------------------------------

是否可以使用一個 SQL 查詢? 我試圖在這里這里“玩”解決方案,但失敗了。

您應該能夠使用相關子查詢。 假設num_value在主表中, f值在num_value中:

select m.*,
       (select first 1 d.f_value
        from detail d
        where d.master_id = m.master_id
        order by abs(m.num_value - d.f_value)
       )
from master m;

編輯:

如果您想要更大的值的偏好 - 如果它存在 - 只需將order by更改為:

order by (case when d.f_value >= m.num_value then 1 else 2 end),
         abs(d.f_value - m.num_value)

讓我們將num_value稱為您正在尋找的針(如“大海撈針”)。

首先,我們將對針進行標准化,使其不低於MIN(f_value)且不高於每個master_idMAX(f_value)

然后,我們將查找每個Detail行,其最近的f_value大於或等於我們的歸一化針,按master_id分組。 (這只是一個最大的每組 sql問題)。

WITH normalized AS (     -- First normalize the needle for each master_id
  SELECT hilo.master_id,
         MAXVALUE(hilo.lo, MINVALUE(hilo.hi, d.needle)) AS needle
    FROM (SELECT ? FROM rdb$database) d (needle) -- <- change this ? to your needle
         CROSS JOIN
         (SELECT master_id, MAX(f_value), MIN(f_value)
            FROM detail GROUP BY master_id) hilo (master_id, hi, lo)
),
     ranked AS (         -- Next order f_value >= needle by master_id
  SELECT detail.*,
         ROW_NUMBER() OVER (PARTITION BY detail.master_id ORDER BY f_value ASC)
           AS rk
    FROM detail
         LEFT JOIN
         normalized ON detail.master_id = normalized.master_id
   WHERE detail.f_value >= normalized.needle
)
                         -- Strip off the rank ordering and SELECT what you want
SELECT id, master_id, f_value, ...
  FROM ranked
 WHERE rk = 1;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM