gpt4 book ai didi

sql - 通过 SQL 查询安全地规范化数据

转载 作者:行者123 更新时间:2023-12-04 21:54:47 25 4
gpt4 key购买 nike

假设我有一张客户表:

CREATE TABLE customers (
customer_number INTEGER,
customer_name VARCHAR(...),
customer_address VARCHAR(...)
)

该表确实 而不是 有主键。但是, customer_namecustomer_address 对于任何给定的 customer_number 都应该是唯一的。

此表包含许多重复客户的情况并不少见。为了避免这种重复,以下查询用于仅隔离唯一客户:
SELECT
DISTINCT customer_number, customer_name, customer_address
FROM customers

幸运的是,该表历来包含准确的数据。也就是说,从来没有任何 customer_namecustomer_addresscustomer_number 发生冲突。但是,假设有冲突的数据确实进入了表格。我希望编写一个会失败的查询,而不是为有问题的 customer_number 返回多行。

例如,我尝试了这个查询但没有成功:
SELECT
customer_number, DISTINCT(customer_name, customer_address)
FROM customers
GROUP BY customer_number

有没有办法使用标准 SQL 编写这样的查询?如果没有,是否有特定于 Oracle 的 SQL 的解决方案?

编辑:奇怪查询背后的基本原理:

说实话,这个客户表实际上并不存在(谢天谢地)。我创建它是希望它足够清楚以证明查询的需求。但是,人们(幸运的是)意识到,基于该示例,我最不担心这种查询的需要。因此,我现在必须剥离一些抽象,并希望恢复我提出这种令人憎恶的 table 的声誉......

我从外部系统收到一个包含发票(每行一张)的平面文件。我逐行读取此文件,将其字段插入到此表中:
CREATE TABLE unprocessed_invoices (
invoice_number INTEGER,
invoice_date DATE,
...
// other invoice columns
...
customer_number INTEGER,
customer_name VARCHAR(...),
customer_address VARCHAR(...)
)

如您所见,来自外部系统的数据是非规范化的。也就是说,外部系统在同一行中包含发票数据及其关联的客户数据。多张发票可能会共享同一个客户,因此可能会有重复的客户数据。

在保证所有客户都在系统中注册之前,系统无法开始处理发票。因此,系统必须识别唯一客户并根据需要对其进行注册。这就是我想要查询的原因: 因为我正在处理非规范化数据,我无法控制
SELECT
customer_number, DISTINCT(customer_name, customer_address)
FROM unprocessed_invoices
GROUP BY customer_number

希望这有助于澄清问题的原始意图。

编辑:好/坏数据示例

澄清一下: customer_namecustomer_address 对于特定的 customer_number 只需要是唯一的
 customer_number | customer_name | customer_address
----------------------------------------------------
1 | 'Bob' | '123 Street'
1 | 'Bob' | '123 Street'
2 | 'Bob' | '123 Street'
2 | 'Bob' | '123 Street'
3 | 'Fred' | '456 Avenue'
3 | 'Fred' | '789 Crescent'

前两行没问题,因为 customer_name 1 的 customer_addresscustomer_number 是相同的。

中间两行很好,因为它是 customer_name 2 的相同 customer_addresscustomer_number (即使另一个 customer_number 具有相同的 customer_namecustomer_address )。

最后两行是 不行 因为 customer_address 3 有两个不同的 customer_number es。

如果针对所有六行运行,我正在寻找的查询将失败。但是,如果只有前四行实际存在, View 应该返回:
 customer_number | customer_name | customer_address
----------------------------------------------------
1 | 'Bob' | '123 Street'
2 | 'Bob' | '123 Street'

我希望这能澄清我所说的“customer_namecustomer_address 冲突”的意思。它们必须是每个 customer_number 唯一的。

我感谢那些解释如何从外部系统正确导入数据的人。 事实上,我已经在做大部分事情了。我 故意 隐藏了我正在做的所有细节,以便更容易专注于手头的问题。此查询并不是唯一的验证形式。我只是认为这会是一个很好的画龙点睛(可以说是最后的防御)。这个问题只是为了调查 SQL 的可能性。 :)

最佳答案

你的方法有缺陷。您不希望成功存储的数据然后在选择上抛出错误 - 这是一个等待发生的地雷,意味着您永远不知道选择何时会失败。

我建议您向表中添加一个唯一键,然后慢慢开始修改您的应用程序以使用此键,而不是依赖任何有意义的数据组合。

然后,您就可以不再关心重复数据了,这些数据一开始就不是真正的重复数据。两个同名的人共享同一个地址是完全可能的。

您还将通过这种方法获得性能改进。

顺便说一句,我强烈建议您标准化您的数据,即将名称分解为 FirstName 和 LastName(也可以选择 MiddleName),并将地址字段分解为每个组件的单独字段(Address1、Address2、City、State、Country , Zip, 或其他)

更新:如果我正确理解您的情况(我不确定我是否理解),您希望防止名称和地址的重复组合出现在表中(即使这在现实生活中可能发生)。这最好通过对这两个字段的唯一约束或索引来完成,以防止插入数据。即,捕获错误 之前 你插入它。这会告诉您导入文件或生成的应用程序逻辑不好,然后您可以选择采取适当的措施。

我仍然认为当你查询时抛出错误在游戏中为时已晚而无法做任何事情。

关于sql - 通过 SQL 查询安全地规范化数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/987893/

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