You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多表查询生成结果表:Case语句致重复行及Damage最大化问题

解决CASE WHEN导致重复行的问题

嘿,我来帮你搞定这个重复行的问题!咱们先理清楚问题出在哪:

你当前的查询用了笛卡尔积连接(直接把三个表丢在FROM里,没指定表之间的关联条件),再加上WHERE里的IN子句筛选,这会导致符合条件的快速技能(f)和蓄力技能(c)组合,和Pokemon_Types_And_Moves中所有Beedrill的记录挨个匹配。如果Pokemon_Types_And_Moves里有多条Beedrill的条目,或者同一条目下的属性有的匹配快速技能类型、有的不匹配,就会生成两条Damage值不同的行——一条是原数值,一条是乘1.2倍的数值。而SELECT DISTINCT因为Damage字段值不一样,根本没法去重。

你的需求是保留每个(f.Name, c.Name)组合下最大的Damage值(也就是触发1.2倍系数的那个,毕竟它更大),所以咱们得用分组聚合来替代DISTINCT,直接取最大值。

下面是修改后的SQL代码:

SELECT 
    f.Name as 'Fast Move',
    MAX(CASE 
        WHEN ptm.Primary_Type = f.Type OR ptm.Secondary_Type = f.Type THEN f.Damage * 1.2 
        ELSE f.Damage 
    END) as 'Damage',
    f.DPS as 'Fast Move DPS',
    c.Name as 'Charged Move',
    c.Damage as 'Charged Move Damage',
    c.DPS as 'Charged Move DPS',
    ((f.Cooldown * CEIL(c.Energy_Required / f.Energy_Generated)) + c.Time) as 'Full Cycle Time',
    ((f.damage * CEIL(c.Energy_Required / f.Energy_Generated)) + c.Damage) as 'Full Cycle Damage',
    ROUND(
        ((f.damage * CEIL(c.Energy_Required / f.Energy_Generated)) + c.Damage) / 
        ((f.Cooldown * CEIL(c.Energy_Required / f.Energy_Generated)) + c.Time), 
        2
    ) as 'Full Cycle DPS'
FROM 
    Fast_Moves f
JOIN 
    Pokemon_Types_And_Moves ptm ON f.Name IN (ptm.Fast_Move_1, ptm.Fast_Move_2, ptm.Fast_Move_3)
JOIN 
    Charged_Moves c ON c.Name IN (ptm.Charged_Move_1, ptm.Charged_Move_2, ptm.Charged_Move_3)
WHERE 
    ptm.Pokemon_Name = 'Beedrill'
GROUP BY 
    f.Name, f.DPS, c.Name, c.Damage, c.DPS, 
    ((f.Cooldown * CEIL(c.Energy_Required / f.Energy_Generated)) + c.Time),
    ((f.damage * CEIL(c.Energy_Required / f.Energy_Generated)) + c.Damage)
ORDER BY 
    f.Name, c.Name;

关键修改点说明:

  • 替换笛卡尔积为JOIN:用JOIN明确表之间的关联条件,避免不必要的重复匹配,逻辑也更清晰。
  • 用MAX()取最大Damage:对每个技能组合(f.Name + c.Name)以及其他不需要聚合的字段分组,直接取Damage的最大值——这样只要有一次触发1.2倍系数的情况,就会保留这个更大的值,自动丢掉原数值的冗余行。
  • 简化WHERE子句:直接在JOIN条件中筛选Beedrill的技能,WHERE只保留Pokemon_Name的过滤,可读性更强。

如果Pokemon_Types_And_Moves里有很多重复的Beedrill技能记录,还可以先用CTE把技能去重,再关联查询,这样效率更高:

-- 先提取Beedrill的所有技能(去重)
WITH BeedrillMoves AS (
    SELECT 
        DISTINCT
        UNNEST(ARRAY[Fast_Move_1, Fast_Move_2, Fast_Move_3]) AS FastMove,
        UNNEST(ARRAY[Charged_Move_1, Charged_Move_2, Charged_Move_3]) AS ChargedMove,
        Primary_Type, Secondary_Type
    FROM Pokemon_Types_And_Moves
    WHERE Pokemon_Name = 'Beedrill'
)
SELECT 
    f.Name as 'Fast Move',
    MAX(CASE 
        WHEN bm.Primary_Type = f.Type OR bm.Secondary_Type = f.Type THEN f.Damage * 1.2 
        ELSE f.Damage 
    END) as 'Damage',
    f.DPS as 'Fast Move DPS',
    c.Name as 'Charged Move',
    c.Damage as 'Charged Move Damage',
    c.DPS as 'Charged Move DPS',
    ((f.Cooldown * CEIL(c.Energy_Required / f.Energy_Generated)) + c.Time) as 'Full Cycle Time',
    ((f.damage * CEIL(c.Energy_Required / f.Energy_Generated)) + c.Damage) as 'Full Cycle Damage',
    ROUND(
        ((f.damage * CEIL(c.Energy_Required / f.Energy_Generated)) + c.Damage) / 
        ((f.Cooldown * CEIL(c.Energy_Required / f.Energy_Generated)) + c.Time), 
        2
    ) as 'Full Cycle DPS'
FROM 
    BeedrillMoves bm
JOIN Fast_Moves f ON f.Name = bm.FastMove
JOIN Charged_Moves c ON c.Name = bm.ChargedMove
GROUP BY 
    f.Name, f.DPS, c.Name, c.Damage, c.DPS, 
    ((f.Cooldown * CEIL(c.Energy_Required / f.Energy_Generated)) + c.Time),
    ((f.damage * CEIL(c.Energy_Required / f.Energy_Generated)) + c.Damage)
ORDER BY 
    f.Name, c.Name;

这个版本先把Beedrill的技能去重,避免后续关联时产生多余的重复项,适合数据量较大的场景。

内容的提问来源于stack exchange,提问作者Dan Plumbley

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:40:47