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フィールドの結果を 2 番目のテーブルの列見出しとしてピボットする方法はありますか?

        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わからず、準備されたステートメントを利用したくないために提供された回答が適切でない場合は、いつでも別のレベルのグループ化を追加して、アプリケーション コードで「ピボット」を実行できます。 . 選択は次のようになります

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 のピボット テーブルに必要な 2 次元配列を次のように構築できます (ここでは PDO を想定していますが、他のライブラリを使用して結果セットを反復処理するための基本的な要点は同じです)。

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