gpt4 book ai didi

sql - SQL复制与空值

转载 作者:塔克拉玛干 更新时间:2023-11-03 06:39:40 25 4
gpt4 key购买 nike

由于一些疯狂的商业原因,从我们的客户那里得到相当混乱的数据,我有以下问题;
1)我有一个表有6个半唯一标识符和一个自动递增的唯一ID。该表有更多字段但是,这些对这次讨论并不重要。字段所包含的数据类型也不准确。
2)我想获得至少参与一个重复关系的所有行的唯一ID的列表。(标识所有表示重复的行对时没有任何附加值。但是,如果解决方案提供了这一点,那么检索一组重复行就相当简单了。所以,那也没关系)
3)副本定义为:
3A)对于这6个字段中的每一个,记录A必须与记录B匹配,或者其中一个必须为空
3b)至少有一个字段必须完全匹配(即两者都不为空)
4)所有可能重复的感兴趣字段都是字符串,而不是空字符串。许多行至少有一个感兴趣的字段为空,但(至少假设我们的摄取逻辑工作正常)没有一个行可以有3个以上的字段为空。
5)精确的字符串内容匹配是可以的我们不需要任何基于正则表达式的、不区分大小写的…有点匹配。
6)表中的实际副本相当罕见。
7)我们正在运行PostgreSQL 9可以使用特定于数据库的功能。
8)该表有500000行因此,下面提供的我刚开始使用的天真的查询需要太长时间才能实现。据推测,它主要在指数时间内运行。理想情况下,运行在中端服务器上的结果应该在一分钟内返回。

SELECT a.id
FROM myTable a
JOIN myTable b ON a.id < b.id
AND (a.field1 = b.field1 OR a.field1 IS NULL OR b.field1 IS NULL )
AND (a.field2 = b.field2 OR a.field2 IS NULL OR b.field2 IS NULL)
....
WHERE
a.field1 = b.field1 OR a.field2 = b.field2 ...

9)我还研究了使用“分组”但是,如果其中一个分组列包含空值,而另一个包含值,则“group by”不认为两行相等。除非有办法实现这种行为,否则group by不适用于我的“两个都相等或至少一个为空”逻辑。
10)可以假定每一行中可能出现的值集与其他列不重叠。也就是说,除了null之外,您不会期望字段1中的值出现在字段2的任何行中。
更新:很抱歉没有信息。我将尽可能地提供一个近似的表模式。不幸的是,所讨论的项目处于防御状态,甚至仅仅是表的字段名就可以显示有关操作安全的信息。
CREATE TABLE a (
id serial NOT NULL PRIMARY KEY,
f1 character varying,
f2 character varying,
f3 character varying,
f4 character varying,
f5 character varying,
f6 character varying,
...Other columns that aren't really relevant
)

CREATE INDEX f1_idx
ON public.a
USING btree
(f1 COLLATE pg_catalog."default");

...Same index for the other 5 fields.

为了便于参考,我将复制Lorenze Albe的问题并在这里回答。
如果你有三排
(1,2,3,4,空,6)
(1, 2, 3, NULL, 5, NULL)

(1, 2, 3, 4, 7, NULL)

哪些是重复的?
(1, 2, 3, NULL, 5, NULL)


(1, 2, 3, 4, 7, NULL)

不重复,因为字段5在两者中均为非空且它们不相等。另外两个是复制品。
为了清楚起见,我将再举几个自己的例子。(为了完整起见,我将以字符串的形式提供行示例。但是,正如我所说的,它们的弦性并不重要,因为我们需要精确的弦匹配。
 ("1", "2", "3", "4", NULL, NULL)


 ("1","2","3",NULL,"9",NULL)

是重复的,因为列4、5和6在至少一个字段中为空,而所有其他字段都相等。
("1", "2", "3", "4", NULL, "6")


("1","2","3",NULL,"9","7")

不是重复的,因为字段6不同,并且都不是空的
以及两个比较典型的实例的实际数据;
(NULL, NULL, "3",   NULL, "5",  "6")


("1", "2",    NULL, "4",  NULL, "6")

是重复的,因为它们不同的所有字段,至少有一面是空的。
(NULL, NULL, "3",   NULL, "5",  "6")


("1", "2",    NULL, "4",  NULL, "6")

是的,这意味着
(NULL, NULL, NULL, "4", "5", "6")


("1", "2", "3", NULL, NULL, NULL)

如果没有至少一个字段完全匹配的要求,则将是重复的。哪些字段为空,哪些不是非常随机的。我们只需要从我们的数据提供程序中至少提供6个字段中的2个。
另一个更新:我更新了第2点,以反映我希望所有参与至少一个重复对的行。所以,对于三排
(1,2,3,4,空,6)
(1, 2, 3, NULL, 5, NULL)

(1, 2, 3, 4, 7, NULL)

这三行都将被返回,因为即使第2行和第3行不被视为彼此重复,但第1行和第2行是重复的,第1行和第3行是重复的,因此这三行都参与重复关系,因此都将被返回。

最佳答案

使用count() over(partition by ...)然后过滤大于1的任何计数的结果:

CREATE TABLE mytable(
ID INTEGER NOT NULL PRIMARY KEY
,col1 VARCHAR(2) NOT NULL
,col2 VARCHAR(2)
,col3 VARCHAR(2) NOT NULL
,col4 VARCHAR(2)
,col5 VARCHAR(2)
,col6 VARCHAR(2)
);
INSERT INTO mytable(ID,col1,col2,col3,col4,col5,col6) VALUES (1001,'a1','b1','c1','d1','e1','f1');
INSERT INTO mytable(ID,col1,col2,col3,col4,col5,col6) VALUES (1002,'a1',NULL,'c1','d1','e1','f1');
INSERT INTO mytable(ID,col1,col2,col3,col4,col5,col6) VALUES (1003,'a1','b1','c1','d1','e1','f1');
INSERT INTO mytable(ID,col1,col2,col3,col4,col5,col6) VALUES (1004,'b1','c1','d1','e1','f1',NULL);
INSERT INTO mytable(ID,col1,col2,col3,col4,col5,col6) VALUES (1005,'a1','b1','c1',NULL,'e1','f1');
INSERT INTO mytable(ID,col1,col2,col3,col4,col5,col6) VALUES (1006,'b1','c1','d1','e1','f1',NULL);
INSERT INTO mytable(ID,col1,col2,col3,col4,col5,col6) VALUES (1007,'f1',NULL,'b1','c1','d1','e1');
INSERT INTO mytable(ID,col1,col2,col3,col4,col5,col6) VALUES (1008,'b1','c1','d1','e1','f1',NULL);
INSERT INTO mytable(ID,col1,col2,col3,col4,col5,col6) VALUES (1009,'c1','d1','e1','f1',NULL,NULL);
INSERT INTO mytable(ID,col1,col2,col3,col4,col5,col6) VALUES (1010,'c1','d1','e1','f1',NULL,'a1');
INSERT INTO mytable(ID,col1,col2,col3,col4,col5,col6) VALUES (1011,'a1','b1','c1','d1','e1','f1');

select
*
, count(*) over(partition by
coalesce(col1,'NULL')
, coalesce(col2,'NULL')
, coalesce(col3,'NULL')
, coalesce(col4,'NULL')
, coalesce(col5,'NULL')
, coalesce(col6,'NULL')
) cv
from mytable

ID COL1 COL2 COL3 COL4 COL5 COL6简历
---::—————————————————————————————————
1001 | a1 | b1 | c1 | d1 | e1 | f1 | 3
1003 | a1 | b1 | c1 | d1 | e1 | f1 | 3
1011 A1 B1 C1 D1 E1 F1 3
1005 A1 B1 C1空E1 F1 1
1002 A1空C1 D1 E1 F1 1
1008 b1 c1 d1 e1 f1空3
1004 b1 c1 d1 e1 f1空3
1006 b1 c1 d1 e1 f1空3
1010 C1 D1 E1 F1空A1 1
1009 C1 D1 E1 F1零零1
1007 f1零b1 c1 d1 e1 1
使用上面的方法作为子查询,然后使用 where cv > 1来定位在这6列中具有“重复项”的所有行。
分贝<>小提琴 here
请注意使用一些样本数据的能力。实际上,您的责任是为您的问题提供样本数据(因为您已经拥有了这些数据)不要试图仅用文字来解释,用数据来说明“现状”和“未来”,你会发现你的问题更容易准备,回答更快。见 Why should I provide a MCVE

关于sql - SQL复制与空值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52979692/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com