我正在尝试写一个复杂的(至少,对于我的知识水平)字符串,但我有一段时间。
这是问题所在。我有两个表,一个名为t1,另一个名为c1。
表格定义如下:
table T1:
e_id, char(8),
e_date, datetime,
e_status, varchar(2)
table C1:
e_id, char(8),
e_date, datetime,
e_status, varchar(2)
每个表都包含两个表中可能找到或未找到的标识符列表(它们在每个表中可能是唯一的,也可能不是唯一的),以及相关的状态(T1表中可以是“OK”或“R”) ,可以是C1表中的'OK'或'C'),以及与e_id的每次出现相关联的日期时间e_date
我正在尝试编写一个查询:
e_date
的所有e_id值。e_status = 'OK'
中找到的每个特定e_id
的{{1}}计数添加到行结果中T1 table
中找到的每个特定e_Status = 'OK'
的{{1}}计数添加到行结果中我会尽力在这里写一些示例数据/结果。为清楚起见,我将忽略表数据类型。假设当前日期和时间是2012年11月8日19:00:00
T1:
C1:
运行查询将产生:
e_id,e_date,e_status,r_count,c_count
1. e_id:'A',e_date: 2012年11月8日10:00:00 ,e_status:'确定',r_count: 6 ,c_count: 2
2. e_id:'A',e_date: 2012年11月8日10:00:00 ,e_status:'R',r_count: 6 ,c_count: 2
3. e_id:'A',e_date: 2012年10月15日10:00:00 ,e_status:'R',r_count: 6 ,c_count: 2
4. e_id:'A',e_date: 2012年10月15日10:00:00 ,e_status:'确定',r_count: 6 ,c_count: 2
5. e_id:'A',e_date: 2012-Oct-15 10:00:00 ,e_status:'R',r_count: 6 ,c_count: 2
6. e_id:'A',e_date: 2012年10月15日10:00:00 ,e_status:'R',r_count: 6 ,c_count: 2
我真的很抱歉,我不得不更改T1行3到7(结果的行3 4 5 6)的日期,因为值是错误的。
由于在过去24小时内未找到e_id
,因此未返回T1的第4行
T1第8和第9行未归还,因为它们超出了过去30天
答案 0 :(得分:2)
时间做一些TDQD - 测试驱动的查询设计。
SELECT DISTINCT e_id
FROM T1
WHERE e_date >= DATE_SUB(NOW(), INTERVAL 24 HOUR)
这将是查询其他部分中普遍存在的子查询。
...过去24小时内T1中有一个条目。
SELECT a.e_id
FROM t1 AS a
JOIN (SELECT DISTINCT e_id
FROM T1
WHERE e_date >= DATE_SUB(NOW(), INTERVAL 24 HOUR)
) AS b ON b.e_id = a.e_id
WHERE a.e_date >= DATE_SUB(NOW(), INTERVAL 30 DAY)
我们可以根据需要添加其他列。
...过去24小时内T1中有一个条目
SELECT a.e_id, COUNT(*) AS r_count -- Per question; why not t_count?
FROM t1 AS a
JOIN (SELECT DISTINCT e_id
FROM T1
WHERE e_date >= DATE_SUB(NOW(), INTERVAL 24 HOUR)
) AS b ON b.e_id = a.e_id
WHERE a.e_status = 'R'
GROUP BY a.e_id
...过去24小时内T1中有一个条目
SELECT a.e_id, COUNT(*) AS c_count
FROM c1 AS a
JOIN (SELECT DISTINCT e_id
FROM T1
WHERE e_date >= DATE_SUB(NOW(), INTERVAL 24 HOUR)
) AS b ON b.e_id = a.e_id
WHERE a.e_status = 'C'
GROUP BY a.e_id
SELECT a.e_id, a.e_date, a.e_status, c.r_count, d.c_count
FROM t1 AS a
JOIN (SELECT DISTINCT e_id
FROM T1
WHERE e_date >= DATE_SUB(NOW(), INTERVAL 24 HOUR)
) AS b ON b.e_id = a.e_id
LEFT JOIN -- Because there might be no OK rows in T1
(SELECT a.e_id, COUNT(*) AS r_count
FROM t1 AS a
JOIN (SELECT DISTINCT e_id
FROM T1
WHERE e_date >= DATE_SUB(NOW(), INTERVAL 24 HOUR)
) AS b ON b.e_id = a.e_id
WHERE a.e_status = 'OK'
GROUP BY a.e_id
) AS c ON c.e_id = a.e_id
LEFT JOIN -- Because there might be no OK rows in C1
(SELECT a.e_id, COUNT(*) AS c_count
FROM c1 AS a
JOIN (SELECT DISTINCT e_id
FROM T1
WHERE e_date >= DATE_SUB(NOW(), INTERVAL 24 HOUR)
) AS b ON b.e_id = a.e_id
WHERE a.e_status = 'OK'
GROUP BY a.e_id
) AS d ON d.e_id = a.e_id
WHERE a.e_date >= DATE_SUB(NOW(), INTERVAL 30 DAY)
您可能可以在没有24小时子查询的情况下编写子查询,但是尽快消除尽可能多的行可能是有效的。
TDQD背后的概念的一个优点是您可以检查中期结果。有一些基本上是微不足道的语法问题(部分原因是因为MySQL不是我的主要DBMS),但是对于两个COUNT子查询,从JOIN到LEFT JOIN的更改是您在组装时易于发现的事情查询。试图让第一时间的一切正确 - 很难,即使不是徒劳的。但逐步建立可以让您对自己所做的事情充满信心。在没有测试组件子查询的情况下,我从不构建像这样复杂的查询。
感谢(次要)更新FatalMojo。