2

大家好,提前感谢您的帮助!

我正在尝试根据返回的查询创建交叉表类型的查询结果。第一个查询:

SELECT DISTINCT
dc.`name`,
Count(pd.dispositionCodeId) AS NumberOfDispos
FROM
pd

 JOIN ph ON (pd.packetHeaderId = ph.packetHeaderId)
 JOIN sc ON (sc.packetHeaderId = ph.packetHeaderId)
 JOIN dc ON pd.dispositionCodeId = dc.dpcodeId
WHERE (`ph`.`customerId` = 60)
GROUP BY
dc.`name`

导致:

Name NumberofDispos
B      400
NO     245
S      134
V      98

-name我返回的内容是可变的,具体取决于 customerId,以及出现在其他类似查询中的附加 where 子句。

有没有办法将name字段的结果作为第二个表中的列标题进行旋转,第二个查询将计算该特定名称出现在另一个匹配字段中的出现次数?

        B   NO  S   V 
PackA   250 120 61  22
PackB   100 23  62  37
PackC   50  102 11  39

请记住,列标题会根据第一次查询的结果而变化。

据我所知,我需要创建一个 php 数组并遍历 sql 结果

4

3 回答 3

2

这种类型的查询称为数据透视,但不幸的是 MySQL 没有数据透视函数,因此您需要使用带有CASE语句的聚合函数来复制它。

如果这些值是提前知道的,那么您可以将这些值硬编码为以下内容:

SELECT pd.dispositionCodeId,
  sum(case when dc.`name` = 'B' then 1 else 0 end) B,
  sum(case when dc.`name` = 'NO' then 1 else 0 end) NO,
  sum(case when dc.`name` = 'S' then 1 else 0 end) S,
  sum(case when dc.`name` = 'V' then 1 else 0 end) V
FROM pd
JOIN ph 
  ON pd.packetHeaderId = ph.packetHeaderId
JOIN sc 
  ON sc.packetHeaderId = ph.packetHeaderId
JOIN dc 
  ON pd.dispositionCodeId = dc.dpcodeId
WHERE (`ph`.`customerId` = 60)
GROUP BY pd.dispositionCodeId;

但是,如果值或数量names未知,那么您可以使用准备好的语句来创建动态 sql 语句来执行。代码将如下所示:

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'sum(case when dc.`name` = ''',
      name,
      ''' then 1 else 0 end) AS ',
      name
    )
  ) INTO @sql
FROM dc;

SET @sql = CONCAT('SELECT pd.dispositionCodeId, ', @sql, ' 
                   FROM pd
                   JOIN ph 
                     ON pd.packetHeaderId = ph.packetHeaderId
                   JOIN sc 
                     ON sc.packetHeaderId = ph.packetHeaderId
                   JOIN dc 
                     ON pd.dispositionCodeId = dc.dpcodeId 
                   WHERE `ph`.`customerId` = 60
                   GROUP BY pd.dispositionCodeId');

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
于 2013-01-10T23:08:20.793 回答
1

这应该适合你:

SELECT 
  pd.dispositionCodeId,
  SUM(CASE WHEN dc.`Name` = 'B' THEN 1 ELSE 0 END 0) AS B,
  SUM(CASE WHEN dc.`Name` = 'NO' THEN 1 ELSE 0 END 0) AS NO,
  SUM(CASE WHEN dc.`Name` = 'S' THEN 1 ELSE 0 END 0) AS S,
  SUM(CASE WHEN dc.`Name` = 'V' THEN 1 ELSE 0 END 0) AS V
FROM pd
JOIN ph ON (pd.packetHeaderId = ph.packetHeaderId)
JOIN sc ON (sc.packetHeaderId = ph.packetHeaderId)
JOIN dc ON pd.dispositionCodeId = dc.dpcodeId
WHERE (`ph`.`customerId` = 60)
GROUP BY pd.dispositionCodeId
于 2013-01-10T22:55:40.127 回答
0

如果提供的答案不合适,因为您事先不知道该name字段的值并且不想使用准备好的语句,您总是可以添加另一个级别的分组并在您的应用程序代码中执行“pivot” . 选择可能看起来像

SELECT
dc.`name` as `name`,
dc.`other_field` as `other_field`,
Count(pd.dispositionCodeId) AS NumberOfDispos
FROM
pd
 JOIN ph ON (pd.packetHeaderId = ph.packetHeaderId)
 JOIN sc ON (sc.packetHeaderId = ph.packetHeaderId)
 JOIN dc ON pd.dispositionCodeId = dc.dpcodeId
WHERE (`ph`.`customerId` = 60)
GROUP BY
dc.`name`,
dc.`other_field`
ORDER BY
dc.`name` ASC,
dc.`other_field` ASC

然后,您可以在 PHP 中构建数据透视表所需的二维数组(假设此处为 PDO,但基本要点与使用其他库遍历结果集相同):

$final_array = array();
while($row = $statement->fetchObject()) {
    $final_array[$row->name][$row->other_field] = $row->NumberOfDispos;
}
于 2013-01-10T23:22:31.647 回答