【发布时间】:2014-05-26 14:37:21
【问题描述】:
我这里有一个奇怪的错误。
我正在尝试将以下查询的结果限制为仅一行/结果:
SELECT userEmail
FROM [LunchUsersAvailable]
WHERE LunchGroupsID = '301' AND availableDate = '2015-01-01' AND userEmail != 'userEmail@company.com' EXCEPT
(
SELECT DISTINCT (COALESCE([user1], [user2])) AS matchedEmail
FROM
(
SELECT [user1], [user2]
FROM [LunchMatched]
UNION ALL
SELECT [user2], [user1]
FROM [LunchMatched]
) AS tmp
WHERE (user1 = 'userEmail@company.com' OR user2 = 'userEmail@company.com')
)
输出:
test2@company.com
test3@company.com
test4@company.com
我尝试使用 TOP 1。没用。完全没有结果。
SELECT TOP 1 userEmail
FROM [LunchUsersAvailable]
WHERE LunchGroupsID = '301' AND availableDate = '2015-01-01' AND userEmail != 'userEmail@company.com' EXCEPT
(
SELECT DISTINCT (COALESCE([user1], [user2])) AS matchedEmail
FROM
(
SELECT [user1], [user2]
FROM [LunchMatched]
UNION ALL
SELECT [user2], [user1]
FROM [LunchMatched]
) AS tmp
WHERE (user1 = 'userEmail@company.com' OR user2 = 'userEmail@company.com')
)
我也用 MIN() 进行了测试。没有结果。
SELECT MIN (userEmail) as email
FROM [LunchUsersAvailable]
WHERE LunchGroupsID = '301' AND availableDate = '2015-01-01' AND userEmail != 'userEmail@company.com' EXCEPT
(
SELECT DISTINCT (COALESCE([user1], [user2])) AS matchedEmail
FROM
(
SELECT [user1], [user2]
FROM [LunchMatched]
UNION ALL
SELECT [user2], [user1]
FROM [LunchMatched]
) AS tmp
WHERE (user1 = 'userEmail@company.com' OR user2 = 'userEmail@company.com')
)
为了以防万一,我使用 MAX() 进行了测试。 有效!
SELECT MAX (userEmail) as email
FROM [LunchUsersAvailable]
WHERE LunchGroupsID = '301' AND availableDate = '2015-01-01' AND userEmail != 'userEmail@company.com' EXCEPT
(
SELECT DISTINCT (COALESCE([user1], [user2])) AS matchedEmail
FROM
(
SELECT [user1], [user2]
FROM [LunchMatched]
UNION ALL
SELECT [user2], [user1]
FROM [LunchMatched]
) AS tmp
WHERE (user1 = 'userEmail@company.com' OR user2 = 'userEmail@company.com')
)
输出:
test4@company.com
总之,我的问题是:我如何获得 test2@company.com 作为结果?
更多测试更新: 我做了两个不同的测试。一个有效,另一个无效。我会详细展示每一个。首先,一切正常的测试:
我想分别解释每个 SELECT 以及每个部分的结果:
-- this outter SELECT lists all available users who are available
SELECT userEmail FROM [LunchUsersAvailable]
WHERE LunchGroupsID = '301' AND availableDate = '2015-01-01' AND userEmail != 'userEmail@company.com'
输出:
test1@company.com
test2@company.com
test3@company.com
test4@company.com
(受影响的 4 行)
-- this inner SELECT lists all the users who has been paired with userEmail@company.com before
SELECT DISTINCT (COALESCE([user1], [user2])) AS matchedEmail
FROM
(
SELECT [user1], [user2]
FROM [LunchMatched]
UNION ALL
SELECT [user2], [user1]
FROM [LunchMatched]
) AS tmp
WHERE (user1 = 'userEmail@company.com' OR user2 = 'userEmail@company.com')
输出:
userEmail@company.com
test2@company.com
(2 行受影响)
运行完整代码,没有 TOP 1、MIN() 或 MAX():
test1@company.com
test3@company.com
test4@company.com
(受影响的 3 行)
到目前为止,这都是正确的。现在我只需要获取 test1@company.com 部分,因此我将代码的第一行从 从 [LunchUsersAvailable] 中选择用户电子邮件 到 从 [LunchUsersAvailable] 中选择前 1 个用户电子邮件
结果是:
test1@company.com
(受影响的 1 行)
这工作绝对很好。
但是现在,如果 userEmail@company.com 之前已经与 test1@company.com 而不是 test2@company.com 匹配([LunchMatched]表)结果不同。
INNER、OUTTER 和 FULL 代码(没有 TOP 1、MIN 或 MAX)的工作方式与上述相同,这很好。
但是,如果我将代码的第一行从 从 [LunchUsersAvailable] 中选择用户电子邮件 到 从 [LunchUsersAvailable] 中选择前 1 个用户电子邮件
结果是 null 而不是正确的: test2@company.com
(受影响的 1 行)
【问题讨论】:
-
附注:您的查询过于复杂。首先,您选择所有 user1-user2 对以及所有 user2-user1 对。然后你删除所有没有合作伙伴是'userEmail\@company.com'的对然后你选择每对的第一个元素,包括删除空值,然后你使用不同的。而您实际上所做的只是:获取所有 user1 和所有 user2 的对话,其中一个合作伙伴是 'userEmail\@company.com'。在这里可以使用一个相当简单的 NOT EXISTS 子句。
-
[LunchMatched] 表存储了之前匹配的对(user1 和 user2)。但它可以节省 userEmail@company.com | userB@company.com 或 userB@company.com | userEmail@company.com。我的代码试图在 [LunchMatched] 表上找到所有与 userEmail@company.com 匹配的人。这就是为什么我需要先做一个 UNION ALL (从双方得到这对)。 SELECT userEmail FROM [LunchUsersAvailable] 列出了所有可用用户,但我不想将 userEmail@company.com 与同一对配对,这就是我使用 EXCEPT 'old pair' 的原因。跨度>