您好,提前谢谢您!
我有一个 SQL 查询,它返回状态为“活动”的课程 ID 的客户列表。我注意到总数不正确,并且有一些缺失的客户没有出现在结果列表中。当我将这些客户包含在 WHERE 子句中时,他们确实出现了。如果它们满足所有其他 WHERE 过滤器,它们不应该在没有直接引用的情况下显示吗?
查询特定客户没有出现在结果列表中的地方
SELECT * FROM COURSES_ACTIVE
WHERE COURSE_ID = '123aaaBBB'
AND COURSE_STATUS = 'Active';
查询特定客户出现在结果列表中的位置
SELECT * FROM COURSES_ACTIVE
WHERE COURSE_ID = '123aaaBBB'
AND COURSE_STATUS = 'Active'
AND CUSTOMER_ID = '555cccDDD';
我尝试过的事情
最初我认为这可能与 ID 需要区分大小写有关,并且可能在之前的 SELECT 语句中,事物与 GROUP BY 的组合不正确。我确保所有 ID 都是 COLLATE("CUSTOMER_ID ", 'binary')。我已在之前的所有查询中确认 CUSTOMER_ID 确实显示,但未将它们包含在 WHERE 子句中。
当我在 SELECT CUSTOMER_ID::VARCHAR 之后粘贴“::VARCHAR”时,我已经获得了正确的 CUSTOMER_ID,但由于它不区分大小写,我担心我再次不会拥有所有 ID。
如果我在 SELECT CUSTOMER_ID::BINAY 的末尾粘贴“::BINARY”,则会收到错误“以下字符串不是合法的十六进制编码值:'888ooo000'”<--this fills with a random CUSTOMER_ID
完整代码
WITH COURSES_ALL AS (SELECT CUSTOMER_ID,
COURSE_ID,
MAX(COURSE_EXPIRATION_DATE) CURRENT_EXPIRATION_DATE
FROM DATABASE
GROUP BY CUSTOMER_ID,
COURSE_ID
-- Course get new row entries so I use MAX to make sure I am only working with the most recent entry.
-- I have confirmed that if I run my query here, all CUSTOMER_IDs show up.
COURSES_ACTIVE AS (SELECT CUSTOMER_ID,
COURSE_ID,
CURRENT_EXPIRATION_DATE,
CASE
WHEN CURRENT_EXPIRATION_DATE < '2024-01-31' THEN 'Inactive'
WHEN CURRENT_EXPIRATION_DATE >= '2024-01-31' THEN 'Active'
END COURSE_STATUS,
FROM COURSES_ALL)
SELECT * FROM COURSES_ACTIVE
WHERE COURSE_ID = '123aaaBBB'
AND COURSE_STATUS = 'Active';
-- AND CUSTOMER_ID = '555cccDDD'; //adding this line back in results in the customer showing up in the results
我建议使用绑定变量来使查询更加灵活,而不是对日期和课程进行硬编码。另外,在当前查询中,您没有在第一个 CTE 中进行过滤,这似乎很浪费,如果您只是要过滤掉这些行,那么计算“非活动”没有多大意义。
所以我建议:
DECLARE @DATE DATE = '2024-01-31';
DECLARE @COURSE_ID VARCHAR = '123aaaBBB';
SELECT CUSTOMER_ID, COURSE_ID, MAX(COURSE_EXPIRATION_DATE) CURRENT_EXPIRATION_DATE
FROM DATABASE
WHERE COURSE_ID COLLATE 'en-cs' = @COURSE_ID COLLATE 'en-cs'
GROUP BY CUSTOMER_ID, COURSE_ID
HAVING MAX(COURSE_EXPIRATION_DATE) >= @DATE;
如果不需要强制执行区分大小写的排序规则,可以将其删除。