SQL由于ETL错误而过滤重复的行

时间:2016-10-07 18:50:17

标签: sql postgresql duplicates filtering

数据库是Postgres,但任何SQL逻辑都应该有所帮助。

我正在检索包含物料清单中给定产品的销售报价集。我分两步执行此操作:步骤1,检索包含给定产品的所有DISTINCT报价编号(按产品编号)。

第二步,检索完整报价,列出每个唯一报价编号的所有产品。

到目前为止,这么好。现在是艰难的一点。有些行是重复的,有些则不是。那些重复的(报价编号和报价版本和行号)可能会或可能不会对它们进行维护。我想选择维护大于0的行。我要排除的重复行是那些维护为0的行。问题是有些行没有重复,有0维护,所以我不能只过滤维护。

为了让这令人兴奋,该数据库保留了20多年的报价。数据科学家们刚刚承认也许 ETL过程有一些错误......

--- step 0
--- cleanup the workspace
SET CLIENT_ENCODING TO 'UTF8';
DROP TABLE IF EXISTS product_quotes;

--- step 1
--- get list of Product Quotes
CREATE TEMPORARY TABLE product_quotes AS (
   SELECT DISTINCT master_quote_number
   FROM w_quote_line_d

   WHERE item_number IN ( << model numbers >> )
);

--- step 2
--- Now join on that list
SELECT 
d.quote_line_number,
d.item_number,
d.item_description,
d.item_quantity,
d.unit_of_measure,
f.ref_list_price_amount,
f.quote_amount_entered,
f.negtd_discount,
--- need to calculate discount rate based on list price and negtd discount (%)
CASE
    WHEN ref_list_price_amount > 0 
        THEN 100 - (ref_list_price_amount + negtd_discount) / ref_list_price_amount *100
    ELSE 0
END AS discount_percent,

f.warranty_months,
f.master_quote_number,
f.quote_version_number,
f.maintenance_months,
f.territory_wid,
f.district_wid,
f.sales_rep_wid,
f.sales_organization_wid,
f.install_at_customer_wid,
f.ship_to_customer_wid,
f.bill_to_customer_wid,
f.sold_to_customer_wid,
d.net_value,
d.deal_score,
f.transaction_date,
f.reporting_date

FROM w_quote_line_d d
INNER JOIN product_quotes pq ON (pq.master_quote_number = d.master_quote_number)

INNER JOIN w_quote_f f ON 
    (f.quote_line_number = d.quote_line_number 
    AND f.master_quote_number = d.master_quote_number 
    AND f.quote_version_number = d.quote_version_number)

WHERE d.net_value >= 0 AND item_quantity > 0
ORDER BY f.master_quote_number, f.quote_version_number, d.quote_line_number

过滤重复行的逻辑如下: 对于每个master_quote_number / version_number对,检查是否存在重复的行号。如果是这样,请选择维护&gt; 0.

即使在CASE声明中,我也不确定如何写。

思考?数据库是Postgres,但任何SQL逻辑都应该有所帮助。

3 个答案:

答案 0 :(得分:0)

你能做点像......

select
    *
from
    w_quote_line_d d
    inner join
        (
            select
                ...
                ,max(maintenance)
            from
                w_quote_line_d
            group by
                ...
        ) d1
   on 
       d1.id = d.id
       and d1.maintenance = d.maintenance;

我是否正确理解您的问题?

编辑:忘记小组!

答案 1 :(得分:0)

我想你会想要使用Window Functions。总之,它们很棒。

这是一个将重复删除&#34;根据您的标准:

select *
from (
    select 
        * -- simplifying here to show the important parts
        ,row_number() over (
            partition by master_quote_number, version_number
            order by maintenance desc) as seqnum
    from w_quote_line_d d
    inner join product_quotes pq 
    on (pq.master_quote_number = d.master_quote_number)
    inner join w_quote_f f 
    on (f.quote_line_number = d.quote_line_number
      and f.master_quote_number = d.master_quote_number 
      and f.quote_version_number = d.quote_version_number)
) x
where seqnum = 1

row_number()以及所选partition byorder by条件的使用保证quote_number / version_number的每个组合只有一行将获得值1,它将是一个维护中具有最高值的人(如果你的同事是对的,那么只有一个值> 0的人)。

答案 2 :(得分:-1)

我不确定,但也许你可以Group By所有其他列,并使用MAX(Maintenance)来获得最大的。

您怎么看?