我在MySQL中生成数据透视表时遇到问题,并想知道是否有人可以给我任何提示和一些文档,这样我就可以最终解决这个问题了。
我的问题如下:
我的数据库中有2个表。 clients
包含客户信息,例如姓名,ssn和一些个人数据。在cli_location
表中是客户位置:地址,电话号码,手机等。
有时我们需要根据位置等标准进行选择,以便在特定城市接客户。我们还根据cpf进行查询,以获取特定客户的信息。
我经常需要跨越这两张桌子。我目前正在做left join
。 left join
的问题在于,有时客户端有多个电话,每个电话会为每个电话生成新行。
在研究如何改善这种行为时,我发现了数据透视表,但是我无法理解它们。
╔════╦══════╦═══════╦════════════╦═══════╦════════╗
║ id ║ name ║ ssn ║ dt_birth ║ store ║ value ║
╠════╬══════╬═══════╬════════════╬═══════╬════════╣
║ 1 ║ john ║ 12345 ║ 1991-11-04 ║ 318 ║ 34.33 ║
║ 2 ║ john ║ 12345 ║ 1991-11-04 ║ 318 ║ 654.44 ║
║ 3 ║ john ║ 12345 ║ 1991-11-04 ║ 212 ║ 238.00 ║
║ 4 ║ alex ║ 54321 ║ 1988-05-20 ║ 321 ║ 334.44 ║
╚════╩══════╩═══════╩════════════╩═══════╩════════╝
╔════╦══════╦═══════╦══════════╦════════╦═════════╦═══════╦══════════╗
║ id ║ name ║ ssn ║ address ║ city ║ state ║ zip ║ tel ║
╠════╬══════╬═══════╬══════════╬════════╬═════════╬═══════╬══════════╣
║ 1 ║ john ║ 12345 ║ street1 ║ city1 ║ state1 ║ 23443 ║ 23432122 ║
║ 2 ║ john ║ 12345 ║ street1 ║ city1 ║ state1 ║ 23443 ║ 98765434 ║
║ 3 ║ john ║ 12345 ║ street2 ║ city5 ║ state7 ║ 54323 ║ 65765567 ║
║ 4 ║ john ║ 12345 ║ street3 ║ city4 ║ state9 ║ 76543 ║ 44323455 ║
║ 5 ║ alex ║ 54321 ║ street34 ║ city30 ║ state33 ║ 43234 ║ 86643457 ║
╚════╩══════╩═══════╩══════════╩════════╩═════════╩═══════╩══════════╝
当使用左连接跨越表时,引用字段为ssn
,结果有许多重复的行。我无法改变生产中的数据结构。
我曾想过做类似的事情:
╔════╦══════╦═══════╦════════════╦═══════╦════════╦════════╦════════╦════════╦════════╦══════════╦════════╦═════════╦═══════╦══════════╦════════╦════════╦════════╦══════════╦════════╦════════╦════════╦══════════╦══════════╦══════════╦══════════╗
║ id ║ name ║ ssn ║ dt_birth ║ store ║ value ║ store1 ║ value1 ║ store2 ║ value2 ║ address ║ city ║ state ║ zip ║ address1 ║ city1 ║ state1 ║ zip1 ║ address2 ║ city2 ║ state2 ║ zip2 ║ tel ║ tel1 ║ tel2 ║ tel3 ║
╠════╬══════╬═══════╬════════════╬═══════╬════════╬════════╬════════╬════════╬════════╬══════════╬════════╬═════════╬═══════╬══════════╬════════╬════════╬════════╬══════════╬════════╬════════╬════════╬══════════╬══════════╬══════════╬══════════╣
║ 1 ║ john ║ 12345 ║ 1991-11-04 ║ 318 ║ 34.33 ║ 318 ║ 654.44 ║ 212 ║ 238.00 ║ street1 ║ city1 ║ state1 ║ 23443 ║ street2 ║ city5 ║ state7 ║ 54323 ║ street3 ║ city4 ║ state9 ║ 76543 ║ 23432122 ║ 98765434 ║ 65765567 ║ 44323455 ║
║ 4 ║ alex ║ 54321 ║ 1988-05-20 ║ 321 ║ 334.33 ║ (null) ║ (null) ║ (null) ║ (null) ║ street34 ║ city30 ║ state33 ║ 43234 ║ (null) ║ (null) ║ (null) ║ (null) ║ (null) ║ (null) ║ (null) ║ (null) ║ (null) ║ 86643457 ║ (null) ║ (null) ║
╚════╩══════╩═══════╩════════════╩═══════╩════════╩════════╩════════╩════════╩════════╩══════════╩════════╩═════════╩═══════╩══════════╩════════╩════════╩════════╩══════════╩════════╩════════╩════════╩══════════╩══════════╩══════════╩══════════╝
这个想法是动态生成列,因为有更多行具有相同类型的信息,如上表所示。即使有2行具有相同的store
,字段value
的值也会有所不同,因此必须为每个store
- value
对添加列。与上表中的address
和phone
字段相同。
如果有人可以给我指点文档,请告诉我任何有助于我学习如何做这类事情的例子或任何事情,我将非常感激!
答案 0 :(得分:0)
进一步考虑这一点,我确信SQL无法完全满足您的需求。 This answer解释原因,并列出您的选择:
left join
查询,然后编写应用程序代码以将结果操作为所需的格式。 然而,如果您愿意将多个值合并到一个列中,group_concat
可能会让您关闭:
select
ssn,
name,
group_concat(distinct tel separator ', ') phones,
group_concat(distinct address separator '; ') addresses
from
(select clients.ssn,
clients.name,
cli_location.tel,
concat(cli_location.address, ', ', city, ' ', zip) address
from clients
left join cli_location
on clients.ssn=cli_location.ssn) c
group by ssn
产生
| SSN | NAME | PHONES | ADDRESSES |
|-------|------|----------------------------------------|------------------------------------------------------------------|
| 12345 | john | 23432122, 44323455, 65765567, 98765434 | street1, city1 23443; street3, city4 76543; street2, city5 54323 |
| 54321 | alex | 86643457 | street34, city30 43234 |
http://sqlfiddle.com/#!2/ca287/25
如果您想要特定城市的客户列表:
select clients.ssn, clients.name
from clients
inner join cli_location
using(ssn)
where city = 'city1'
group by ssn;
http://sqlfiddle.com/#!2/ca287/3
你的架构使这比应该更加困难。考虑对其进行规范化,使客户端名称只在一个表中,并将一对多关系(如client:phone)拆分为单独的表。