我有一个如下所示的数据集。
EMPLID PHONE_TYPE PHONE
------ ---------- --------
100 HOME 111-1111
100 WORK 222-2222
101 HOME 333-3333
102 WORK 444-4444
103 OTHER 555-5555
我想使用PHONE_TYPE字段为每位员工选择一行来建立首选项。如果员工有一个,我想要家庭电话号码,如员工100和101的情况。如果不存在家庭电话号码,我想要工作号码(员工102),作为最后的手段,我会带其他与员工103一样的数字。实际上我的表有大约十几个PHONE_TYPE字段的值,所以我需要能够扩展任何解决方案,以包括不仅仅是我在示例中显示的三个值。有什么想法吗?感谢。
答案 0 :(得分:3)
您需要添加phone_types表(Phone_Type TEXT(Whatever),Priority INTEGER)。在此表中,列出每个Phone_Type值一次并为其指定优先级(在您的示例中,HOME将为1,WORK 2,OTHER 3等等。)
然后,创建一个将优先级列从Phone_Types连接到Phone_Numbers表的视图(假设我们称之为Phone_Numbers_Ex)。
现在,您可以通过MIN(优先级)为给定的emplID从Phone_Numbers_Ex获取记录的几个选项,其中最明显的可能是:
SELECT * FROM Phone_Numbers_Ex P1 WHERE NOT EXISTS
(SELECT * FROM Phone_Numbers_Ex P2 WHERE P2.EmplID = P1.EmplID AND P2.Priority < P1.Priority)
另一种方法是沿SELECT EmplID, MIN(Priority) AS Priority FROM Phone_Numbers_Ex GROUP BY EmplID
的行声明另一个视图或内部查询,然后在EmplID和Priority上加入后面的Phone_Numbers_Ex。
答案 1 :(得分:2)
我忘了,Server 2000是否支持Coalesce?如果确实如此,我认为这将有效:
Select Distinct EmplID, Coalesce(
(Select Phone from Employees where emplid = e1.emplid and phone_type = 'HOME'),
(Select Phone from Employees where emplid = e1.emplid and phone_type = 'WORK'),
(Select Phone from Employees where emplid = e1.emplid and phone_type = 'OTHER')
) as Phone
From Employees e1
答案 2 :(得分:0)
如果允许员工拥有指定电话类型的多个电话号码,则您的要求可能不完整。我添加了一个phone_number_id只是为了让事情变得独一无二,并假设如果这个人有两个相同类型的手机,你会想要最低的id。这很随意,但您可以用自己的业务逻辑替换它。
我还假设了某种Phone_Types表,其中包含应该使用哪个电话号码的优先级。如果您还没有此表,则应该添加它。如果不出意外,它允许您使用外键约束手机类型。
SELECT
PN1.employee_id,
PN1.phone_type,
PN1.phone_number
FROM
Phone_Numbers PN1
INNER JOIN Phone_Types PT1 ON
PT1.phone_type = PN1.phone_type
WHERE
NOT EXISTS
(
SELECT *
FROM
Phone_Numbers PN2
INNER JOIN Phone_Types PT2 ON
PT2.phone_type = PN2.phone_type AND
(
(PT2.priority < PT1.priority)
--OR (PT2.priority = PT1.priority AND PN2.phone_number_id > PN1.phone_number_id)
)
)
您也可以使用LEFT JOIN而不是NOT EXISTS来实现此功能,或者如果您正在寻找单个员工的电话号码,则可以使用TOP。只需按优先顺序排列TOP 1 ORDER,phone_number_id。
最后,如果你要升级到SQL 2005或SQL 2008,你可以使用带有ROWNUMBER()OVER(ORDER BY priority,phone_number,PARTITION BY employee_id)的CTE&lt; - 我想我的语法可能略有偏差用括号括起来,但希望它足够清楚。这将允许您通过检查ROWNUMBER()= 1来获得所有员工的最高职位。
答案 3 :(得分:0)
作为替代g.d.d.c在Select子句中使用查询的答案,您可以使用左连接。你可能会得到更好的性能,但你当然应该测试。
SELECT
e1.iD,
Coalesce(phoneHome.Phone,phoneWork.Phone,phoneOther) phone
FROm
employees e1
LEFT JOIN phone phoneHome
ON e1.emplId = phoneHome
and phone_type = 'HOME'
LEFT JOIN phone phoneWork
ON e1.emplId = phoneWork
and phone_type = 'WORK'
LEFT JOIN phone phoneWork
ON e1.emplId = phoneOTHER
and phone_type = 'OTHER'