如何编写正确的创建表语句?
MySQL 与 PostgreSQL
关于第一个问题:您的查询无效。您按 customer_code 分组并选择 market_code。但是一个 customer_code 有很多行,那么要选择哪个 market_code 呢?你忘了告诉 DBMS。因此,两个 DBMS 都应该抛出错误。如果 MySQL 没有,这可能意味着您正在使用一个旧的 MySQL 版本,该版本设置为 MySQL 在开始时遇到GROUP BY 子句和功能依赖关系问题时发明的作弊模式。确保在 MySQL 中 SET sql_mode = 'ONLY_FULL_GROUP_BY'; 在编写此类无效查询时获得正确的语法错误消息 - 或使用默认模式为当前 MySQL 版本。
至于第二个问题,这不是那么容易回答的……
数据库规范化
您正在处理一个非规范化表。它一次又一次地显示同一区域同一市场的同一客户。这很容易出错。您希望同一个客户总是在同一个市场中,但如果某些交易并非如此呢?您期望一个代码完全属于一个市场名称,但如果表中并非总是如此,该怎么办?您期望一个市场位于一个区域,同样,如果并非所有交易都属于这种情况怎么办?
假设您的所有期望都是有效的,而违反这些期望的数据是错误的。
纠正不一致
所以,首先要找到数据不一致的地方。我在这里使用 PostgreSQL,因为尽管有 MySQL 标签,这似乎是您想要使用的。
select customer_code, string_agg(distinct market_code, ',' order by market_code)
from transactions
group by customer_code
having count(distinct market_code) > 1;
如果此查询返回具有多个市场的客户,请修复您的数据。例如。:
update transactions
set market_code = 'Mark001'
where customer_code = 'Cus001';
市场代码也一样。查询:
select market_code, string_agg(distinct market_name, ',' order by market_name)
from transactions
group by market_code
having count(distinct market_name) > 1;
更新不一致的数据:
update transactions
set market_name = 'Darbhanga'
where market_code = 'Mark001';
市场区域也一样。查询:
select market_code, string_agg(distinct zone, ',' order by zone)
from transactions
group by market_code
having count(distinct zone) > 1;
更新不一致的数据:
update transactions
set zone = 'Bihar'
where market_code = 'Mark001';
规范化数据库
完成后,构建您的表。是的,不仅仅是一张客户表,因为这仍然是非规范化的并且承担同样的风险。相反,我们有区域、市场、客户和交易。
您可以使用技术 ID 或单独使用您的代码。我在这里根据您的代码构建表格,但选择权在您。
区域
create table zone
(
zone_code varchar(100) not null,
zone varchar(100) not null,
primary key (zone_code),
unique (zone)
);
insert into zone (zone_code, zone)
select distinct upper(zone), zone
from transactions;
市场
create table market
(
market_code varchar(100) not null,
name varchar(100) not null,
zone_code varchar(100) not null,
primary key (market_code),
unique (name),
constraint fk_market_zone foreign key(zone_code) references zone(zone_code)
);
insert into market (market_code, name, zone_code)
select distinct market_code, market_name, upper(zone)
from transactions;
顾客
create table customer
(
customer_code varchar(100) not null,
market_code varchar(100) not null,
primary key (customer_code),
constraint fk_customer_market foreign key(market_code) references market(market_code)
);
insert into customer (customer_code, market_code)
select distinct customer_code, market_code
from transactions;
交易
从表中删除现在多余的列。它们现在隐含在客户身上。
alter table transactions
drop column market_code,
drop column market_name,
drop column zone;