2012-04-20 38 views
2

我正在玩一些SQL,所以如果我在求职面试中被问到,我并不完全无知。我的朋友最近在一次采访中被问到了下面的问题,他无法得到它,并且我问了一个在工作中知道SQL并且他不知道的人。你们能为我回答这个问题,然后解释它是如何工作的?请?将未规范化的列选择为单独的记录?

* 问题 *

数据库标准化(或缺乏规范化的)往往呈现为开发人员提出了挑战。

考虑员工的数据库表包含三个字段:

EmployeeID 
EmployeeName 
EmailAddresses 

每一位员工,由唯一标识雇员,可能有一个或更多的逗号分隔,@ rockauto.com电子邮件地址(ES) EmailAddresses字段。

数据库表定义如下:

CREATE TABLE Employees 
(
    EmployeeID int UNSIGNED NOT NULL PRIMARY KEY, 
    EmployeeName varchar(50) NOT NULL, 
    EmailAddresses varchar(40) NOT NULL , 
    PRIMARY KEY(EmployeeID) 
); 

出于测试目的,这里是一些样本数据:

INSERT INTO Employees (EmployeeID, EmployeeName, EmailAddresses) VALUES 
('1', 'Bill', '[email protected]'), 
('2', 'Fred', '[email protected],[email protected]'), 
('3', 'Fred', '[email protected]'), 
('4', 'Joe', '[email protected],[email protected]'); 

你的任务是写一个单一的MySQL SELECT查询,将呈现以下输出为上面的采样数据:

Employee EmailAddress 
Bill [email protected] 
Fred (2) [email protected] 
Fred (2) [email protected] 
Fred (3) [email protected] 
Joe  [email protected] 
Joe  [email protected] 

请注意是因为存在多个具有相同名称的人(在本例中为“Fred”),EmployeeID包含在括号中。

您的查询需要用MySQL 5.1.41版本的兼容语法编写。您应该假定使用标准数据库升序排序来完成排序:“ORDER BY EmployeeID ASC”

对于此问题,您需要提交一个SQL SELECT查询。您的查询应该能够在合理的时间内处理一个包含1000条记录的表格。

+9

只是我的看法...这是一个糟糕的面试问题。 – bobwienholt 2012-04-20 16:50:02

+0

我们允许使用php来解析select语句,或者查询是否必须直接以该格式拉取 – squarephoenix 2012-04-20 16:53:08

+2

更好的问题是如何规范化这个数据库结构^^ – 2012-04-20 16:53:14

回答

1

仅当您的电子邮件少于10000封....是否可以接受?

select 
     if(t1.c > 1, concat(e.employeename, ' (', e.employeeid, ')'), e.employeename) as Employee, 
     replace(substring(substring_index(e.EmailAddresses, ',', n.row), length(substring_index(e.EmailAddresses, ',', n.row - 1)) + 1), ',', '') EmailAddress 
from 
     (select employeename, count(*) as c from Employees group by employeename) as t1, 
     (select EmployeeID, length(EmailAddresses) - length(replace(EmailAddresses,',','')) + 1 as emails from Employees) as t2, 
     (SELECT @row := @row + 1 as row FROM 
     (select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) x, 
     (select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) x2, 
     (select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) x3, 
     (select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) x4, 
     (SELECT @row:=0) as ff) as n, 
     Employees e 
where 
     e.employeename = t1.employeename and 
     e.employeeid = t2.employeeid and 
     n.row <= t2.emails 
order by e.employeeid; 

编辑:

以较少的无用数时:

select 
     if(t1.c > 1, concat(e.EmployeeName, ' (', e.EmployeeID, ')'), e.EmployeeName) as Employee, 
     replace(substring(substring_index(e.EmailAddresses, ',', n.row), length(substring_index(e.EmailAddresses, ',', n.row - 1)) + 1), ',', '') as EmailAddress 
from 
     (select EmployeeName, count(*) as c from Employees group by EmployeeName) as t1, 
     (select EmployeeID, length(EmailAddresses) - length(replace(EmailAddresses,',','')) + 1 as emails from Employees) as t2, 
     (select `1` as row from (select 1 union all select 2 union all select 3 union all select 4) x) as n, 
     Employees e 
where 
     e.EmployeeName = t1.EmployeeName and 
     e.EmployeeID = t2.EmployeeID and 
     n.row <= t2.emails 
order by e.EmployeeID; 

,做我们学到什么?糟糕的数据库设计导致可怕的查询。而且你可以用SQL做东西,这可能仅仅是因为人们做的数据库设计不佳...... :)

+0

电子邮件字段只有40个字符长,所以不会有事件适合在那里 – 2012-04-20 18:14:32

+0

好点...数字生成可以显着简化。显然,没有办法在MySQL中生成参数化的行数。 – Toni 2012-04-20 18:25:46