SQL Server 2000 - 根据单元格值从多行中选择一行

发布于 12-19 07:04 字数 1971 浏览 2 评论 0原文

我遇到了一个有趣的困境,困扰着我和一位同事。我正在尝试构建一个 sql 查询,该查询将允许我提取员工的电话分机并将其发布在公共网站上。在我们的电话系统(基于 SQL Server 2000)中,一个用户最多可以拥有三个分机(到目前为止):一个 3XXX 号码(直线)、一个 5XXX(老板组,适合有秘书和多线电话的人)和7XXX(语音邮件)。

大多数人的分机号不是 3XXX 就是 7XXX。只有少数人拥有 5XXX,但我们也有人通过促销获得了额外的号码。例如,一名教师(仅获得语音信箱/7XXX)晋升为助理校长并获得直线/3XXX,然后成为主任并获得秘书,因此为 5XXX。

我们希望按照 5XXX、3XXX、7XXX 的顺序发布这些数字,因此大多数使用 ORDER BY 的直接路由都不适用。我已经得到了查询,它将返回类似这样的内容:

UserID | Extension |Employee ID 
-------------------------------
USER 1 | 3234      |1234
USER 1 | 5235      |1234
USER 1 | 7364      |1234

但是,由于它们的扩展被添加到系统中,所以我不能依赖它们可能所处的顺序。我也无法控制删除其他扩展。

我们尝试做一些案例陈述,但没有遇到什么好的结果。下面是我们正在使用的 SQL,它变得非常复杂,超出了我的能力范围。任何人都可以阐明我们如何智能地在每一行中获取一个值,该值将根据上面的规则返回员工 ID 和电话分机号?名字、姓氏只是为了检查,而不是最终的一部分。

抱歉,如果这听起来很多,我只是在这里感到绝望。

SELECT DISTINCT 
FirstName, LastName, PrimaryFaxNumber, MAX(CASE WHEN Expr1 IS NOT NULL THEN Expr1 ELSE CASE WHEN Expr2 IS NOT NULL 
                      THEN Expr2 ELSE Expr3 END END) AS Extension
FROM         (SELECT     sub.FirstName, sub.LastName, sub.PrimaryFaxNumber, da.DtmfAccessId, CASE WHEN LEFT(CAST(da.DtmfAccessId AS nvarchar), 1) 
                                              = '5' THEN da.DtmfAccessId END AS Expr1, CASE WHEN LEFT(CAST(da.DtmfAccessId AS nvarchar), 1) 
                                              = '3' THEN da.DtmfAccessId END AS Expr2, CASE WHEN LEFT(CAST(da.DtmfAccessId AS nvarchar), 1) 
                                              = '7' THEN da.DtmfAccessId END AS Expr3
                       FROM          Subscriber sub FULL OUTER JOIN
                                              DtmfAccessId da ON da.ParentObjectId = sub.SubscriberObjectId
                       WHERE      (sub.SubscriberObjectId IS NOT NULL) AND (sub.PrimaryFaxNumber IS NOT NULL) AND (CAST(da.DtmfAccessId AS BIGINT) < 9999)) 
                      DERIVEDTBL
GROUP BY FirstName, LastName, PrimaryFaxNumber
ORDER BY LastName, FirstName

I've got an interesting dilemma that has stumped me and a coworker. I'm trying to construct a sql query that will allow me to pull phone extensions for an employee to be published on a public website. In our phone system (SQL Server 2000 based) a user can have up to three extensions (so far): a 3XXX number (direct line), a 5XXX (boss groups, for a person with a secretary and multi-line phones) and a 7XXX (voicemail).

Most people have either a 3XXX or 7XXX extension. Only a few have the 5XXX, but we also have people who, via promotions, have gained additional numbers. For example, a teacher (who only gets a voicemail/7XXX) was promoted to Assistance Principal and gets a direct line/3XXX and then become a Director and gets a secretary, thus a 5XXX.

We want to publish these numbers in the order of 5XXX then 3XXX then 7XXX, so most of the direct routes using ORDER BY are out the window. I've gotten the query to the point where it will return something like this:

UserID | Extension |Employee ID 
-------------------------------
USER 1 | 3234      |1234
USER 1 | 5235      |1234
USER 1 | 7364      |1234

I cannot, however, rely on the order that they may be in, due to when their extension was added to the system. I also have no control over removing the other extensions.

We tried doing some case statements but ran into nothing very good. Below is the SQL we are using which is becoming very complicated and is way over my head. Can anyone shine some light on how we can intelligently get one value into each row that would return the employee ID and phone extension based on the rules from above? The firstname, lastname stuff is just for checking and not part of the final.

Sorry if this sound like a lot, just getting desperate over here.

SELECT DISTINCT 
FirstName, LastName, PrimaryFaxNumber, MAX(CASE WHEN Expr1 IS NOT NULL THEN Expr1 ELSE CASE WHEN Expr2 IS NOT NULL 
                      THEN Expr2 ELSE Expr3 END END) AS Extension
FROM         (SELECT     sub.FirstName, sub.LastName, sub.PrimaryFaxNumber, da.DtmfAccessId, CASE WHEN LEFT(CAST(da.DtmfAccessId AS nvarchar), 1) 
                                              = '5' THEN da.DtmfAccessId END AS Expr1, CASE WHEN LEFT(CAST(da.DtmfAccessId AS nvarchar), 1) 
                                              = '3' THEN da.DtmfAccessId END AS Expr2, CASE WHEN LEFT(CAST(da.DtmfAccessId AS nvarchar), 1) 
                                              = '7' THEN da.DtmfAccessId END AS Expr3
                       FROM          Subscriber sub FULL OUTER JOIN
                                              DtmfAccessId da ON da.ParentObjectId = sub.SubscriberObjectId
                       WHERE      (sub.SubscriberObjectId IS NOT NULL) AND (sub.PrimaryFaxNumber IS NOT NULL) AND (CAST(da.DtmfAccessId AS BIGINT) < 9999)) 
                      DERIVEDTBL
GROUP BY FirstName, LastName, PrimaryFaxNumber
ORDER BY LastName, FirstName

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

那片花海2024-12-26 07:04:26

选择所有 5xxx UNION 3xx,但不选择 5xxx union 7xxx,但不选择 5xxx 或 3xxx。

实际查询将如下所示:

SELECT DISTINCT EmployeeID, Extension 
    FROM AccessId 
        WHERE LEFT(CAST(Extension AS nvarchar), 1)='5' 
UNION
SELECT DISTINCT EmployeeID, Extension 
    FROM AccessId 
        WHERE LEFT(CAST(Extension AS nvarchar), 1)='3' 
            AND NOT EXIST (
                SELECT EmployeeID FROM AccessId 
                    WHERE LEFT(CAST(Extension AS nvarchar), 1)='5')
UNION
SELECT DISTINCT EmployeeID, Extension 
    FROM AccessId 
            WHERE LEFT(CAST(Extension AS nvarchar), 1)='7' 
                AND NOT EXIST (
                    SELECT EmployeeID FROM AccessId 
                        WHERE LEFT(CAST(Extension AS nvarchar), 1)='3' 
                            OR LEFT(CAST(Extension AS nvarchar), 1)='5');

但可能存在更快的解决方案。

Do a select of all 5xxx UNION 3xx but not 5xxx union 7xxx but not 5xxx or 3xxx.

Actual query will look like this:

SELECT DISTINCT EmployeeID, Extension 
    FROM AccessId 
        WHERE LEFT(CAST(Extension AS nvarchar), 1)='5' 
UNION
SELECT DISTINCT EmployeeID, Extension 
    FROM AccessId 
        WHERE LEFT(CAST(Extension AS nvarchar), 1)='3' 
            AND NOT EXIST (
                SELECT EmployeeID FROM AccessId 
                    WHERE LEFT(CAST(Extension AS nvarchar), 1)='5')
UNION
SELECT DISTINCT EmployeeID, Extension 
    FROM AccessId 
            WHERE LEFT(CAST(Extension AS nvarchar), 1)='7' 
                AND NOT EXIST (
                    SELECT EmployeeID FROM AccessId 
                        WHERE LEFT(CAST(Extension AS nvarchar), 1)='3' 
                            OR LEFT(CAST(Extension AS nvarchar), 1)='5');

There might exist faster solutions though.

_蜘蛛2024-12-26 07:04:26

如果我理解正确的话,您所需要做的就是按 LEFT(extension,1) 对结果进行排序,这样您就可以得到

SELECT * FROM (your_your_query)a
ORDER BY a.user_id, CASE LEFT(a.extension,1)
WHEN '5' THEN 1
WHEN '3' THEN 2
WHEN '7' THEN 3
ELSE 4
END

If I understood you right, all you need is to sort your result by LEFT(extension,1), so you will have

SELECT * FROM (your_your_query)a
ORDER BY a.user_id, CASE LEFT(a.extension,1)
WHEN '5' THEN 1
WHEN '3' THEN 2
WHEN '7' THEN 3
ELSE 4
END
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文