以下是我的问题:如何使用聚合函数和分组来保持记录完整性?
进一步解释,这是一个例子。
我有一个包含以下列的表:(将其视为“订单”表)
Customer_Summary (first 10 char of name + first 10 char of address)
Customer_Name
Customer_Address
Customer_Postal Code
Order_weekday
每个“订单”有一行,因此许多行具有相同的客户名称,地址和摘要。
我想要做的是显示客户的姓名,地址和邮政编码,以及他们在每个工作日放置的订单数量,按客户摘要分组。
所以数据看起来应该是这样的:
Summary | Name | Address | PCode | Monday | Tuesday | Wednesday | Thursday | Friday
test custntest addre|test custname|test address|123456 | 1 | 1 | 1 | 1 | 1
我只想将类似客户摘要的记录组合在一起,但显然我想要显示一个名称,地址和邮政编码。我现在正在使用min(),所以我的查询看起来像:
SELECT Customer_Summary, min(customer_name), min(customer_address), min(customer_postal_code)
FROM Order
Group by customer_summary
我省略了我的工作日逻辑,因为我觉得没必要。
我的问题是这一点 - 其中一些拥有相同客户摘要的客户有不同的地址和邮政编码。
所以我可能有两个客户,看起来像:
test custntest addre|test custname |test address |323456|
test custntest addre|test custname2|test address2|123456|
使用group by,我的查询将返回以下内容:
test custntest addre|test custname |test address |123456|
由于我使用min,它会给我所有字段的最小值,但不一定来自同一记录。所以我在这里丢失了我的记录完整性 - 查询返回的地址和名称与邮政编码没有正确匹配。
那么在使用group by子句时如何在非分组字段上维护数据完整性?
希望我能够清楚地解释清楚,并提前感谢您的帮助。
编辑:解决了。谢谢大家!答案 0 :(得分:3)
您始终可以使用ROW_NUMBER
代替GROUP BY
WITH A AS (
SELECT Customer_Summary, customer_name, customer_address, customer_postal_code,
ROW_NUMBER() OVER (PARTITION BY Customer_Summary ORDER BY customer_name, customer_address) AS rn
FROM Order
)
SELECT Customer_Summary, customer_name, customer_address, customer_postal_code
FROM A
WHERE rn = 1
然后您可以自由订购在ORDER BY子句中使用的客户。目前,我按名称订购,然后致电。
修改强>
我的解决方案符合您的要求。但我肯定同意其他人:如果你被允许改变数据库结构,这将是一个好主意......你不是(看到你的评论)。好吧,那么ROW_NUMBER()是一个好方法。
答案 1 :(得分:3)
我认为你需要重新思考你的结构。
理想情况下,您将拥有一个具有唯一ID的Customer
表。然后,您将在Order
表中使用该唯一ID。然后你不需要你正在使用的奇怪的“前10个字符”方法。相反,您只需按Customer
表中的唯一ID进行分组。
您甚至可以拥有一个单独的地址表,将每个地址与客户相关联,多行(其中字段标记为家庭住址,送货地址,帐单地址等)。
这样您就可以将客户信息与地址信息和订单信息分开。这样,如果客户更改姓名(婚姻)或地址(搬家),则不会破坏您的数据 - 所有内容都与ID相关,而不是数据本身。
[此关系称为外键。]