Sql 做一个计数查询?

Sql 做一个计数查询?,sql,mysql,pivot,Sql,Mysql,Pivot,我有下表: UID | ID | Type 1 | 1 | product 1 | 2 | product 1 | 3 | service 1 | 4 | product 1 | 5 | product 2 | 6 | service 1 | 7 | order 2 | 8 | invoice 2 | 9 | product 我想以以下方式结束: UID | product | service | invoice | o

我有下表:

UID | ID  | Type
1   | 1   | product
1   | 2   | product
1   | 3   | service
1   | 4   | product
1   | 5   | product
2   | 6   | service
1   | 7   | order
2   | 8   | invoice
2   | 9   | product
我想以以下方式结束:

UID | product | service | invoice | order
1   |  4      |  1      |  0      |  1
2   |  1      |  1      |  1      |  0

SQL查询是什么样子的?或者至少是最充分的一个?

从mytable中选择countproduct、service、invoice、order

您正在寻找一种称为pivot表的东西,MySQL本机无法做到这一点

在这种情况下,您最好转换应用程序中的数据,并使用GROUP BY和/或DISTINCT的组合来收集您要查找的数据。此查询可能有效,但我尚未对其进行测试:

SELECT Type, COUNT(ID), UID
  FROM tablename
 GROUP BY UID, Type

如果您确实只需要这四种类型,那么您可以按如下方式硬编码值:

select UID,
    count(case when type='product' then 1 else null end) as product,
    count(case when type='service' then 1 else null end) as service,
    count(case when type='invoice' then 1 else null end) as invoice,
    count(case when type='order' then 1 else null end) as order
from MyTable
group by UID
order by UID    
您必须使用MySQL将行数据转换为列,反之亦然:

  SELECT t.uid,
         SUM(CASE WHEN t.type = 'product' THEN COUNT(*) END) as PRODUCT,
         SUM(CASE WHEN t.type = 'service' THEN COUNT(*) END) as SERVICE,
         SUM(CASE WHEN t.type = 'invoice' THEN COUNT(*) END) as INVOICE,
         SUM(CASE WHEN t.type = 'order' THEN COUNT(*) END) as ORDER
    FROM TABLE t
GROUP BY t.uid, t.type

您要做的是透视操作,SQL语法不直接支持透视操作。但是,它并不太复杂,概念上包括两个步骤:

将数据放大为许多列,在原始数据集中每行一行。这通常是在。。。其他的结束或偶尔使用oracle中的解码功能。在下面的示例中,我将使用CASE,因为它同样适用于大多数RDBMS 使用GROUP BY和AGGRATE函数SUM、MIN、MAX等将多行折叠到所需的输出行集中。 我将此数据集用作示例:

mysql> select * from foo;
+------+------+---------+
| uid  | id   | type    |
+------+------+---------+
|    1 |    1 | product | 
|    1 |    2 | product | 
|    1 |    3 | service | 
|    1 |    4 | product | 
|    1 |    5 | product | 
|    2 |    6 | service | 
|    1 |    7 | order   | 
|    2 |    8 | invoice | 
|    2 |    9 | product | 
+------+------+---------+
步骤1是放大数据集:

select uid
     , case when type = 'product' then 1 else 0 end as is_product
     , case when type = 'service' then 1 else 0 end as is_service
     , case when type = 'invoice' then 1 else 0 end as is_invoice
     , case when type = 'order' then 1 else 0 end as is_order
  from foo;
其中:

+------+------------+------------+------------+----------+
| uid  | is_product | is_service | is_invoice | is_order |
+------+------------+------------+------------+----------+
|    1 |          1 |          0 |          0 |        0 | 
|    1 |          1 |          0 |          0 |        0 | 
|    1 |          0 |          1 |          0 |        0 | 
|    1 |          1 |          0 |          0 |        0 | 
|    1 |          1 |          0 |          0 |        0 | 
|    2 |          0 |          1 |          0 |        0 | 
|    1 |          0 |          0 |          0 |        1 | 
|    2 |          0 |          0 |          1 |        0 | 
|    2 |          1 |          0 |          0 |        0 | 
+------+------------+------------+------------+----------+
接下来,我们在每个日期的输出中折叠到一行,并使用或初始查询作为内联视图或子查询,对每个is_*列求和:

select uid
     , sum(is_product) as count_product
     , sum(is_service) as count_service
     , sum(is_invoice) as count_invoice
     , sum(is_order)   as count_order
  from (
         select uid
              , case when type = 'product' then 1 else 0 end as is_product
              , case when type = 'service' then 1 else 0 end as is_service
              , case when type = 'invoice' then 1 else 0 end as is_invoice
              , case when type = 'order' then 1 else 0 end as is_order
           from foo
       ) x
 group by uid;
还请注意,您可以将这两个查询合并为一个查询,尽管为了清晰起见,我在这里分别显示了它们;至少在MySQL中,这似乎导致了一个更简单的执行计划,这通常意味着更快的执行-一如既往,在真实的数据集上测试SQL性能,不要相信我的话

这给了我们:

+------+---------------+---------------+---------------+-------------+
| uid  | count_product | count_service | count_invoice | count_order |
+------+---------------+---------------+---------------+-------------+
|    1 |             4 |             1 |             0 |           1 | 
|    2 |             1 |             1 |             1 |           0 | 
+------+---------------+---------------+---------------+-------------+

这是期望的结果。

如果我相信问题中所写的内容,他不想将类型列值作为列标题吗?这将以稍微不同的方式输出。即一行接一行,而不是一行中的所有内容。但它会成功的!谢谢@威尔,这是真的。我不能认为这是对的,因为它没有回答我的问题。这当然有助于tho.MySQL正确处理工会。正如我在回答中所说的,他真正想要的是一个透视表,但MySQL并没有做到这一点。这是一个解决这一限制的方法。这是其中的一部分——每一行只包含其中一列的计数。我想如果您将其包装在另一个查询中,并选择maxproduct。。。按uid分组它将得到你想要的。我也必须尝试这种方法。你会说这比奥伯曼的建议更有效吗?奥伯曼的解决方案基本上是我提到的折叠版本。。。他使用count和nulls而不是sum,但基本上采取相同的步骤。至于哪一个更有效,你必须在你的桌子上两个都试一下,然后找出答案。此外,EXPLAIN-ANALYZE可以帮助您了解MySQL正在做什么以及可能需要多长时间。