You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

使用Distinct仍有重复行?如何在任意筛选条件成立时查询唯一行?

嘿,我懂你现在的糟心情况——明明加了DISTINCT,结果查出来还是一堆重复行,这大概率是多表左连接加上OR条件搞出来的笛卡尔积在捣乱!

为啥DISTINCT没用?

你的SQL里用了三次左连接,而且WHERE子句里的OR条件会悄悄改变左连接的逻辑(比如涉及eng表字段的条件,会把左连接变成类似内连接的效果)。更关键的是:如果engref表中同一个DRAWING对应多条记录,连接后就会生成大量组合行。DISTINCT只能去掉完全一模一样的行,但只要eng.OP_PSI或者其他字段有差异,这些行就会被保留,看起来还是重复的。

解决方法,按需选一个就行

假设你要的是DRAWING为唯一标识的不重复数据行,试试下面几种方案:

方案一:先筛选符合条件的DRAWING,再关联表

先把满足筛选条件的DRAWING单独拎出来,再和其他表关联,避免过早连接产生冗余:

SELECT r.DRAWING, r.[DESC], r.CF3 AS rCF3, e.OP_PSI
FROM (
    -- 先找出所有符合条件的DRAWING,去重
    SELECT DISTINCT t.DRAWING
    FROM thk t
    LEFT JOIN eng e ON e.DRAWING = t.DRAWING
    WHERE t.SurveyNumber = @SurveyNumber 
       OR CAST(e.L_RATE AS DECIMAL(10,0)) >= 14 
       OR CAST(e.S_RATE AS DECIMAL(10,0)) >= 14 
       OR (YEAR(GETDATE()) - YEAR(t.LastModifiedDate) >= 5) -- 补全你没写完的时间条件
) AS filtered_drawings
LEFT JOIN ref r ON r.DRAWING = filtered_drawings.DRAWING
LEFT JOIN eng e ON e.DRAWING = filtered_drawings.DRAWING
-- 如果eng表一个DRAWING有多条记录,这里可以用聚合函数取一个值,比如MAX(e.OP_PSI)
GROUP BY r.DRAWING, r.[DESC], r.CF3, e.OP_PSI

方案二:用窗口函数精准去重,保留每个DRAWING的一条记录

如果eng表同一个DRAWING有多个记录,你可以指定保留哪一条(比如OP_PSI最大的、最新的):

WITH ranked_data AS (
    SELECT 
        r.DRAWING, 
        r.[DESC], 
        r.CF3 AS rCF3, 
        e.OP_PSI,
        -- 按DRAWING分组,给每条记录排名,排序规则可以按需改
        ROW_NUMBER() OVER (PARTITION BY r.DRAWING ORDER BY e.OP_PSI DESC) AS rn
    FROM thk t
    LEFT JOIN eng e ON e.DRAWING = t.DRAWING
    LEFT JOIN ref r ON r.DRAWING = t.DRAWING
    WHERE t.SurveyNumber = @SurveyNumber 
       OR CAST(e.L_RATE AS DECIMAL(10,0)) >= 14 
       OR CAST(e.S_RATE AS DECIMAL(10,0)) >= 14 
       OR (YEAR(GETDATE()) - YEAR(t.LastModifiedDate) >= 5)
)
SELECT DRAWING, [DESC], rCF3, OP_PSI
FROM ranked_data
WHERE rn = 1 -- 只取每个DRAWING的第一条记录

方案三:调整连接逻辑,用聚合避免笛卡尔积

如果ref表的DRAWING本身是唯一的,可以以ref为主表,关联满足条件的thkeng,同时对eng的字段做聚合:

SELECT 
    r.DRAWING, 
    r.[DESC], 
    r.CF3 AS rCF3, 
    MAX(e.OP_PSI) AS OP_PSI -- 用MAX/MIN取一个合适的OP_PSI值,按需调整
FROM ref r
LEFT JOIN thk t ON r.DRAWING = t.DRAWING
LEFT JOIN eng e ON r.DRAWING = e.DRAWING
WHERE t.SurveyNumber = @SurveyNumber 
   OR CAST(e.L_RATE AS DECIMAL(10,0)) >= 14 
   OR CAST(e.S_RATE AS DECIMAL(10,0)) >= 14 
   OR (YEAR(GETDATE()) - YEAR(t.LastModifiedDate) >= 5)
GROUP BY r.DRAWING, r.[DESC], r.CF3

小提醒

如果你的筛选条件里涉及左连接表的字段(比如e.L_RATE),左连接会自动变成内连接——因为NULL值无法满足>=14的条件。如果需要保留thk中没有对应eng记录但满足其他条件的行,可以把部分条件移到ON子句里,比如:

LEFT JOIN eng e ON e.DRAWING = t.DRAWING 
    AND (CAST(e.L_RATE AS DECIMAL(10,0)) >= 14 OR CAST(e.S_RATE AS DECIMAL(10,0)) >= 14)

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

火山引擎 最新活动