如何根据条件从同一个table中selectMySQL中的数据并避免重复?

How to select data in MySQL from the same table based on conditions and avoid duplicates?

我已经阅读了相关答案,但没有找到解决问题的办法。请帮助我解决以下问题:我有两个 table,我想根据男高音来匹配它们,但考虑到在一个 table 中我可以有不同的条目满足这个条件。在我想从中提取信息 (inst) 的 table 中,我有几个关于利率的数据,所有数据都在不同的行上构建,例如我可以拥有 LIBOR 或 OIS 数据。 我想执行以下查询:将第二个 table (stgy) 的男高音与第一个 table (inst) 的数据相匹配,以获得可用的 OIS,否则,让LIBOR 数据。 下面是我试过但没有用的代码:

SELECT  CASE
    WHEN stgy.tenor IN ('1D','1W','2W','3W','1M','2M','3M','4M','5M','6M','7M','8M','9M','10M','11M')
    THEN ( CASE WHEN security_type='OIS' THEN
                (SELECT price_last FROM inst WHERE currency = @base_crncy AND trade_date = @date_of_interest AND tenor = stgy.tenor)
            ELSE
                (SELECT price_last
               FROM inst                                                                                  
              WHERE security_type IN  ('LIBOR') AND currency = @base_crncy AND trade_date = @date_of_interest
            ) 
            END AS rate 
        )
       ELSE NULL
END AS int_rate

我也是在同一个交易日同币种进行配对。请考虑我也可以有其他 security_type。感谢您的帮助!

更新查询:

     SELECT CASE WHEN stgy.tenor IN('1D','1W','2W','3W','1M','2M','3M','4M','5M','6M','7M','8M','9M','10M','11M')      
      THEN (COALESCE((SELECT price_last FROM instruments WHERE security_type='OIS' AND currency=@base_crncy AND trade_date = @date_of_interest AND tenor=stgy.tenor),
                        (SELECT price_last FROM instruments WHERE security_type='LIBOR' AND currency = @base_crncy AND trade_date = @date_of_interest AND tenor=stgy.tenor)) 
                      )
        ELSE NULL

        END AS int_rate
-- and here i add from where based on the join between the tables (this part works)

首先,为简化起见,您似乎只想从 "stgy" table 中查询特定的基础货币和列表中的 "tenor" 值。

SELECT
      s.tenor
   FROM 
      stgy s
   WHERE 
          s.currency = @base_crncy
      AND s.tenor IN ('1D', '1W', '2W', '3W', '1M', '2M', '3M', '4M',
                      '5M', '6M', '7M', '8M', '9M', '10M', '11M')

因此,您需要 "inst" table 相同期限、货币和交易日期的汇率。现在,要获得最后的价格,它是基于证券类型的。

SELECT
      s.tenor, 
      COALESCE( i.price_last, i2.price_last ) as Price_Last
   FROM 
      stgy s
         LEFT JOIN inst i
            ON s.currency = i.currency
           AND s.tenor = i.tenor
           AND i.trade_date = @date_of_interest 
           AND i.securityType = 'OIS' 
         LEFT JOIN inst i2
            ON s.currency = i2.currency
           AND i2.trade_date = @date_of_interest 
           AND i2.securityType = 'LIBOR' 
   WHERE 
          s.currency = @base_crncy
      AND s.tenor IN ('1D', '1W', '2W', '3W', '1M', '2M', '3M', '4M',
                      '5M', '6M', '7M', '8M', '9M', '10M', '11M')

为了帮助优化查询,我会在

上包含一个索引
stgy   ( currency, tenor )
inst   ( currency, trade_date, tenor, security_type )

创建索引的语法...

ALTER TABLE `stgy` ADD INDEX `currency_tenor` (`currency`, `tenor` );
ALTER TABLE `inst` ADD INDEX `cur_trade_ten_sec` (`currency`, `trade_date, `tenor`, `security_type` );

现在,您可能需要调整以下条件:

       AND case when s.securityType = 'OIS' 
                then s.tenor = i.tenor
                else s.security_type IN ('LIBOR') end

因为您没有显示 table 结构,也没有示例数据(您可以编辑原始问题以提供此类 SAMPLE 数据。

此外,您提到了防止重复...所谓重复,您是指给定货币、trade_date、期限、证券类型的多个条目(也不确定您的 table "security_type" 字段实际上与).

我通过对 inst table 进行两次左连接进行了修改。请分别确认所需条件。看起来您的 "OIS" 条件也需要加入 "tenor" 字段,但不是 "LIBOR" 值。但请注意,左连接分别明确地在 "OIS" 或 "LIBOR" 上,因此给定的 OIS/TENOR 不应有多个条目,也不应为给定的 date/currency 在 LIBOR 上重复.

然后,通过 COALESCE() 提取价格。如果第一个值为 NULL,则从第二列获取值。如果那也是空的,那么您的最后一列答案将为空,这正是您想要得到的。