Mysql 如何在子查询中分组,或者如何实现输出

Mysql 如何在子查询中分组,或者如何实现输出,mysql,Mysql,这是我的疑问: 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

这是我的疑问:

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  | P1 | P2 | P3 |
+--------+----+----+----+
|8/1/2016|  1 |NULL|  1 |
+--------+----+----+----+
|8/2/2016|NULL|  1 |NUll|
+--------+----+----+----+
|8/3/2016| 1  |NULL|NULL|
+--------+----+----+----+

为什么在选择列表中需要子查询?无需多次扫描该表

dte-BETWEEN
谓词中的文本看起来像是
DATE
值。但是对于
DATE
literals,这些格式无效。如果
dte
列是字符串类型(
CHAR
VARCHAR
),并且您正在
dte
列中存储日期值。。。你做错了

考虑查询中发生的情况,将
dte
(字符串)值
'08/15/1999'
作为字符串进行比较。例如,测试此条件:

 SELECT '08/15/1999' BETWEEN '08/01/2016' AND '09/16/2016'
评估为真。(就字符串比较而言,这是正确的。但如果我们将这些值视为日期,那么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:

  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 )

如果有某种(难以理解的)原因需要在选择列表中使用子查询,则可以使用相关子查询。只需从子查询内部的外部查询中引用
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

在选择列表中使用相关子查询通常比使用条件聚合模式更昂贵。这是因为外部查询返回的每一行都会执行子查询。如果外部查询返回一千行,子查询将执行一千次。

您应该编辑您的问题并显示您尝试过的内容。我不能按每个选项分组,我可以做些什么来实现我想要的输出?难道没有人会提到房间里的大象吗?什么是“08/01/2016”?那怎么可能是介于两者之间呢?
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