使用无序字段作为条件为每个员工精确选择一行
我有一个如下所示的数据集。
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 字段值,因此我需要能够扩展任何解决方案以包含不仅仅是示例中显示的三个值。有什么想法吗?谢谢。
I have a data set that looks like the following.
EMPLID PHONE_TYPE PHONE
------ ---------- --------
100 HOME 111-1111
100 WORK 222-2222
101 HOME 333-3333
102 WORK 444-4444
103 OTHER 555-5555
I want to select exactly one row for each employee using the PHONE_TYPE field to establish preferences. I want the HOME phone number if the employee has one as is the case for employee 100 and 101. If the HOME number is not present, I want the WORK number (employee 102), and as a last resort I'll take the OTHER number as with employee 103. In reality my table has about a dozen values for the PHONE_TYPE field, so I need to be able to extend any solution to include more than just the three values I've shown in the example. Any thoughts? Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您需要添加一个phone_types表(Phone_Type TEXT(Whatever),Priority INTEGER)。在此表中,列出每个 Phone_Type 值一次并为其分配优先级(在您的示例中,HOME 为 1、WORK 2、OTHER 3 等)。
然后,创建一个视图,将 Phone_Types 中的 Priority 列连接到 Phone_Numbers 表(假设我们将其称为 Phone_Numbers_Ex)。
现在,对于如何从 Phone_Numbers_Ex 获取给定 emplID 的 MIN(Priority) 记录,您有多种选择,其中最清楚的可能是:
另一种方法是沿着
行声明另一个视图或内部查询SELECT EmplID, MIN(Priority) AS Priority FROM Phone_Numbers_Ex GROUP BY EmplID
,然后在 EmplID 和 Priority 上加入此后的 Phone_Numbers_Ex。You need to add a phone_types table (Phone_Type TEXT(Whatever), Priority INTEGER). In this table, list each Phone_Type value once and assign a priority to it (in your example, HOME would be 1, WORK 2, OTHER 3 and so on).
Then, create a view that joins the Priority column from Phone_Types to your Phone_Numbers table (imagine we call it Phone_Numbers_Ex).
Now, you have several options for how to get record from Phone_Numbers_Ex with the MIN(Priority) for a given emplID, of which probably the clearest is:
Another way is to declare another view, or inner query, along the lines of
SELECT EmplID, MIN(Priority) AS Priority FROM Phone_Numbers_Ex GROUP BY EmplID
and then joining this back Phone_Numbers_Ex on both EmplID and Priority.我忘了,Server 2000 支持 Coalesce 吗?如果是的话,我认为这会起作用:
I forget, does Server 2000 support Coalesce? If it does, I think this will work:
如果允许员工针对给定电话类型拥有多个电话号码,您的要求可能不完整。我添加了一个phone_number_id只是为了使事情变得独特,并假设如果这个人有两部相同类型的电话,您会想要最低的id。这是相当任意的,但您可以用自己的业务逻辑替换它。
我还假设了某种 Phone_Types 表,其中包含应使用哪个电话号码的优先级。如果您还没有此表,您可能应该添加它。如果不出意外的话,它可以让您使用外键来限制电话类型。
您还可以使用 LEFT JOIN 而不是 NOT EXISTS 来实现此操作,或者如果您要查找单个员工的电话号码,则可以使用 TOP。只需执行 TOP 1 ORDER BY 优先级,phone_number_id。
最后,如果您要升级到 SQL 2005 或 SQL 2008,您可以使用 CTE 和 ROWNUMBER() OVER (ORDER BYpriority,phone_number,PARTITION BYemployee_id) <-我认为我的语法可能与括号略有不同对此,但希望它足够清楚。这样您就可以通过检查 ROWNUMBER() = 1 来获取所有员工的第一名。
Your requirements may not be complete if an employee is allowed to have more than one phone number for a given phone type. I've added a phone_number_id just to make things unique and assumed that you would want the lowest id if the person has two phones of the same type. That's pretty arbitrary, but you can replace it with your own business logic.
I've also assumed some kind of a Phone_Types table that includes your priority for which phone number should be used. If you don't already have this table, you should probably add it. If nothing else, it lets you constrain the phone types with a foreign key.
You could also implement this with a LEFT JOIN instead of the NOT EXISTS or you could use TOP if you were looking for the phone number for a single employee. Just do a TOP 1 ORDER BY priority, phone_number_id.
Finally, if you were to move up to SQL 2005 or SQL 2008, you could use a CTE with ROWNUMBER() OVER (ORDER BY priority, phone_number, PARTITION BY employee_id) <- I think my syntax may be slightly off with the parentheses on that, but hopefully it's clear enough. That would allow you to get the top one for all employees by checking that ROWNUMBER() = 1.
作为在 Select 子句中使用查询的替代 gddc 答案,您可以使用左连接。您可能会获得更好的表现,但您当然应该进行测试。
As an alternative g.d.d.c's answer that uses queries in the Select clause you could use left joins. You might get better perf, but you should test of course.