我这里有一个奇怪的错误。
我正在尝试将以下查询的结果限制为仅一行/结果:
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行(s)受影响)
-- 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行(s)受影响)
运行完整代码,没有 TOP 1,MIN()或MAX():
test1@company.com
test3@company.com
test4@company.com
(3行受影响)
到目前为止所有正确的。现在我只需要获得 test1@company.com 部分,所以我改变了代码的第一行 SELECT userEmail FROM [LunchUsersAvailable] 至 SELECT TOP 1 userEmail FROM [LunchUsersAvailable]
结果是:
test1@company.com
(1行受影响)
绝对正常。
但现在,如果 userEmail@company.com 先前已与 test1@company.com而非test2@company.com 匹配([LunchMatched]表)结果不同。
INNER,OUTTER和FULL代码(没有TOP 1,MIN或MAX)的工作方式与上面说明的相同,很好。
但是,如果我更改代码的第一行 SELECT userEmail FROM [LunchUsersAvailable] 至 SELECT TOP 1 userEmail FROM [LunchUsersAvailable]
结果是 null ,而不是正确的结果: test2@company.com
(1行受影响)
答案 0 :(得分:1)
这表明userEmail
接受多个值,其中一个是空字符串(''
- 而不是NULL
)。
userEmail
返回的第一行具有此空值。 min()
会抓住它。 max()
没有。
选中userEmail <> ''
或只使用max()
。
如果您想要min()
,您还可以使用带有case
的条件聚合:
select min(case when userEmail > '' then userEmail end)
编辑:
我看到了问题。 top 1
,min()
和max()
引用except
之前的第一个查询。我错过了except
,因为它在行尾滚动了。 except
的作用类似于union
,将查询连接在一起。它不是where
子句的一部分。
答案 1 :(得分:0)
我明白了! TOP 1或MIN正在处理之前 EXCEPT,这意味着它将首先从可用用户结果获得TOP 1,并且只有他们应用EXCEPTION。
解决方案:获取可用用户的完整列表,运行例外,然后获取TOP 1
SELECT TOP 1 useremail FROM (
SELECT userEmail
FROM [LunchUsersAvailable]
WHERE LunchGroupsID = '301' AND availableDate = '2015-01-01' AND userEmail != 'userEmail@company.com' EXCEPT -- from a specific cafeteria and date, EXCEPT
(
SELECT DISTINCT (COALESCE([user1], [user2])) AS matchedEmail -- select all matched users in one column
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') -- who has been previously matched with the user who is registering now
)
) as tmp
答案 2 :(得分:0)
这不是答案。这只是为了说明如何简化原始查询。以下是三种可能性:
SELECT userEmail
FROM LunchUsersAvailable
WHERE LunchGroupsID = '301'
AND availableDate = '2015-01-01'
AND userEmail != 'userEmail@company.com'
EXCEPT
(
SELECT user1
FROM LunchMatched
WHERE user2 = 'userEmail@company.com'
UNION ALL
SELECT user2
FROM LunchMatched
WHERE user1 = 'userEmail@company.com'
);
或者:
SELECT userEmail
FROM LunchUsersAvailable
WHERE LunchGroupsID = '301'
AND availableDate = '2015-01-01'
AND userEmail != 'userEmail@company.com'
AND userEmail NOT IN
(
SELECT user1
FROM LunchMatched
WHERE user2 = 'userEmail@company.com'
)
AND userEmail NOT IN
(
SELECT user2
FROM LunchMatched
WHERE user1 = 'userEmail@company.com'
);
或者:
SELECT userEmail
FROM LunchUsersAvailable
WHERE LunchGroupsID = '301'
AND availableDate = '2015-01-01'
AND userEmail != 'userEmail@company.com'
AND NOT EXISTS
(
SELECT *
FROM LunchMatched
WHERE LunchUsersAvailable.userEmail IN (LunchMatched.user1, LunchMatched.user2)
AND 'userEmail@company.com' IN (LunchMatched.user1, LunchMatched.user2)
);
在第二个和第三个查询中,可以轻松地将userEmail替换为MIN(userEmail)。在第一个中,这将通过SELECT MIN(userEmail) FROM (first query here)
完成。