这是我的疑问:
\begin{enumerate}[Stage 1]
表
SELECT dte,((SELECT COUNT(prdt) as P1 FROM table
WHERE prdt LIKE '%P1%' AND stat= 'Done' AND dte BETWEEN '08/01/2016' AND '09/07/2016') as P1,
(SELECT COUNT(prdt) as P2 FROM table
WHERE prdt LIKE '%P2%' AND stat= 'Done' AND dte BETWEEN '08/01/2016' AND '09/07/2016') as P2,
(SELECT COUNT(prdt) as P3 FROM table
WHERE prdt LIKE '%P3%' AND stat= 'Done' AND dte BETWEEN '08/01/2016' AND '09/07/2016') as P3
FROM table WHERE dte BETWEEN '08/01/2016' AND '09/07/2016' GROUP BY dte
这就是我想要的输出:
+-------------------+
| dte1 |prdct|stat|
+--------+-----+----+
|8/1/2016| P1 |Done|
+--------+-----+----+
|8/2/2016| P2 |Done|
+--------+-----+----+
|8/3/2016| P1 |Done|
+--------+-----+----+
|8/1/2016| P3 |Done|
+--------+-----+----+
答案 0 :(得分:2)
为什么在SELECT列表中需要子查询?无需多次扫描表格。
dte BETWEEN
谓词中的文字看起来似乎是DATE
值。但是那些DATE
文字的格式不正确。如果dte
列是字符串类型(CHAR
或VARCHAR
),并且您要将日期值存储在dte
列中......那么您做错了。
考虑将dte
(字符串)值'08/15/1999'
的查询中的内容作为字符串进行比较。例如,测试这个条件:
SELECT '08/15/1999' BETWEEN '08/01/2016' AND '09/16/2016'
评估为TRUE。 (就字符串比较而言,这是事实。但如果我们将这些值视为日期,那么1999年的日期将在2016年的两个日期之间没有意义。)
但是,将问题日期格式问题放在一边,并解决您提出的问题......
只需使用条件聚合编写查询。例如:
SELECT t.dte
, SUM( t.stat = 'Done' AND t.prdt LIKE '%P1%' ) AS P1
, SUM( t.stat = 'Done' AND t.prdt LIKE '%P2%' ) AS P2
, SUM( t.stat = 'Done' AND t.prdt LIKE '%P3%' ) AS P3
FROM table t
WHERE t.dte BETWEEN '2016-08-01' AND '2016-09-07'
GROUP BY t.dte
该查询将返回“零”计数,这与规范不匹配。为了匹配规范,并返回NULL值代替零,我们可以使用方便的NULLIF
函数将NULL计数替换为NULL:
SELECT t.dte
, NULLIF(SUM( t.stat = 'Done' AND t.prdt LIKE '%P1%' ),0) AS P1
, NULLIF(SUM( t.stat = 'Done' AND t.prdt LIKE '%P2%' ),0) AS P2
, NULLIF(SUM( t.stat = 'Done' AND t.prdt LIKE '%P3%' ),0) AS P3
FROM table t
WHERE t.dte BETWEEN '2016-08-01' AND '2016-09-07'
GROUP BY t.dte
对于更符合ANSI标准的版本,请替换MySQL简写
NULLIF(SUM( t.stat = 'Done' AND t.prdt LIKE '%P1%' ),0)
带
SUM( CASE WHEN t.stat = 'Done' AND t.prdt LIKE '%P1%' THEN 1 END )
如果您需要在SELECT列表中使用子查询有一些(不可思议的)原因,您可以使用相关子查询。只需从子查询中的外部查询引用dte
的值。
SELECT t.dte
, ( SELECT NULLIF(COUNT(*),0)
FROM table t1
WHERE t1.dte = t.dte
AND t1.prdt LIKE '%P1%'
AND t1.stat = 'Done'
) AS P1
, ( SELECT NULLIF(COUNT(*),0)
FROM table t2
WHERE t2.dte = t.dte
AND t2.prdt LIKE '%P2%'
AND t2.stat = 'Done'
) AS P1
, ( SELECT NULLIF(COUNT(*),0)
FROM table t3
WHERE t3.dte = t.dte
AND t3.prdt LIKE '%P3%'
AND t3.stat = 'Done'
) AS P3
FROM table t
WHERE t.dte BETWEEN '2016-08-01' AND '2016-09-07'
GROUP BY t.dte
在SELECT列表中使用相关子查询通常比使用条件聚合模式更昂贵。那是因为子查询是为外部查询返回的每一行执行的。如果外部查询返回一千行,则子查询将被执行一千次。