1

データ収集環境用のCSVスタイルのデータの「正規化された」データベースからデータを抽出するのに苦労しています。これはPHP/MySQL / JSONを使用して実行され、目的はデータをプロットすることです。フィルタリングの部分があると思いますが、ピボットのサポートが必要です。アイデアは、keyNamesフィールドをデータのフィルターとして使用することです。

クエリは次のとおりです。

select d.testId,d.rowId,f.keyName,f.keyValue from tests t 
inner join data d on t.testId = d.testId 
inner join data c on t.testId = c.testId and c.rowId = d.rowId 
join data f on f.testId = t.testId and f.rowId = d.rowId 
where (d.keyName = 'voltage' and d.keyValue < 5) and (c.keyName = 'temperature' and c.keyValue = 30) and (t.testType = 'testType1');

そして結果:

+--------+-------+-------------+----------+
| testId | rowId | keyName     | keyValue |
+--------+-------+-------------+----------+
|      1 |     1 | voltage     |        4 |
|      1 |     1 | temperature |       30 |
|      1 |     1 | velocity    |       20 |
|      1 |     2 | voltage     |        4 |
|      1 |     2 | temperature |       30 |
|      1 |     2 | velocity    |       21 |
|      2 |     1 | voltage     |        4 |
|      2 |     1 | temperature |       30 |
|      2 |     1 | velocity    |       30 |
|      2 |     2 | voltage     |        4 |
|      2 |     2 | temperature |       30 |
|      2 |     2 | velocity    |       31 |
+--------+-------+-------------+----------+

これを次のようにピボットしたいと思います:testId、rowId、電圧、温度、速度、たとえば:

+--------+-------+---------+-------------+----------+
| testId | rowId | voltage | temperature | velocity |
+--------+-------+---------+-------------+----------+
|      1 |     1 |       4 |          30 |       20 |
|      1 |     2 |       4 |          30 |       21 |
|      2 |     1 |       4 |          30 |       30 |
|      2 |     2 |       4 |          30 |       31 |
+--------+-------+---------+-------------+----------+

何か案は?私はこれに近づいているように感じます:

mysql> select f.testId,f.rowId,(if(f.keyName='voltage',f.keyValue,NULL)) as 'voltage',(if(f.keyName='temperature',f.keyValue,NULL)) as 'temperature',(if(f.keyName='velocity',f.keyValue,NULL)) as 'velocity' from tests t  inner join data d on t.testId = d.testId  inner join data c on t.testId = c.testId and c.rowId = d.rowId  join data f on f.testId = t.testId and f.rowId = d.rowId  where (d.keyName = 'voltage' and d.keyValue < 5) and (c.keyName = 'temperature' and c.keyValue = 30) and (t.testType = 'testType1');
+--------+-------+---------+-------------+----------+
| testId | rowId | voltage | temperature | velocity |
+--------+-------+---------+-------------+----------+
|      1 |     1 |       4 |        NULL |     NULL |
|      1 |     1 |    NULL |          30 |     NULL |
|      1 |     1 |    NULL |        NULL |       20 |
|      1 |     2 |       4 |        NULL |     NULL |
|      1 |     2 |    NULL |          30 |     NULL |
|      1 |     2 |    NULL |        NULL |       21 |
|      2 |     1 |       4 |        NULL |     NULL |
|      2 |     1 |    NULL |          30 |     NULL |
|      2 |     1 |    NULL |        NULL |       30 |
|      2 |     2 |       4 |        NULL |     NULL |
|      2 |     2 |    NULL |          30 |     NULL |
|      2 |     2 |    NULL |        NULL |       31 |
+--------+-------+---------+-------------+----------+

参照用のテーブル定義とデータソースは次のとおりです。

CREATE TABLE IF NOT EXISTS `data` (
  `ptId` int(11) NOT NULL AUTO_INCREMENT,
  `testId` int(11) NOT NULL,
  `rowId` int(11) NOT NULL,
  `keyName` text NOT NULL,
  `keyValue` int(11) NOT NULL,
  PRIMARY KEY (`ptId`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=33 ;

INSERT INTO `data` (`ptId`, `testId`, `rowId`, `keyName`, `keyValue`) VALUES
(1, 1, 1, 'voltage', 4),
(2, 1, 1, 'temperature', 30),
(3, 1, 1, 'velocity', 20),
(4, 1, 2, 'voltage', 4),
(5, 1, 2, 'temperature', 30),
(6, 1, 2, 'velocity', 21),
(7, 1, 3, 'voltage', 3),
(8, 1, 3, 'temperature', 35),
(9, 1, 3, 'velocity', 22),
(10, 1, 4, 'voltage', 3),
(11, 1, 4, 'temperature', 35),
(12, 1, 4, 'velocity', 23),
(13, 2, 1, 'voltage', 4),
(14, 2, 1, 'temperature', 30),
(15, 2, 1, 'velocity', 30),
(16, 2, 2, 'voltage', 4),
(17, 2, 2, 'temperature', 30),
(18, 2, 2, 'velocity', 31),
(19, 2, 3, 'voltage', 5),
(20, 2, 3, 'temperature', 35),
(21, 2, 3, 'velocity', 32),
(22, 2, 4, 'voltage', 5),
(23, 2, 4, 'temperature', 35),
(24, 2, 4, 'velocity', 33),
(25, 4, 1, 'voltage', 4),
(26, 4, 1, 'velocity', 30),
(27, 4, 2, 'voltage', 4),
(28, 4, 2, 'velocity', 31),
(29, 4, 3, 'voltage', 5),
(30, 4, 3, 'velocity', 32),
(31, 4, 4, 'voltage', 5),
(32, 4, 4, 'velocity', 33);

CREATE TABLE IF NOT EXISTS `tests` (
  `testId` int(11) NOT NULL AUTO_INCREMENT COMMENT 'Unique Test ID',
  `testType` text NOT NULL,
  `startDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `userName` text NOT NULL,
  `testSoftware` text NOT NULL,
  `comments` text,
  `dutID` text,
  PRIMARY KEY (`testId`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=8 ;

INSERT INTO `tests` (`testId`, `testType`, `startDate`, `userName`, `testSoftware`, `comments`, `dutID`) VALUES
(1, 'testType1', '2013-03-23 21:06:10', 'testUser1', 'testSoftware1', NULL, 'dut1'),
(2, 'testType1', '2013-03-23 21:10:32', 'testUser1', 'testSoftware1', NULL, 'dut1'),
(3, 'testType1', '2013-03-23 21:10:32', 'testUser1', 'testSoftware1', NULL, 'dut1'),
(4, 'testType2', '2013-03-23 21:10:32', 'testUser1', 'testSoftware1', NULL, 'dut1');
4

1 に答える 1

1

問題の一部は、SELECT リストで集計関数を使用しているが、GROUP BY. GROUP BYこれに似たものを使用する必要があります:

GROUP BY d.testId, d.rowId

集計関数を使用していて、select に他の列がある場合は常に、それらは group by にある必要があります。したがって、完全なクエリは次のようになります。

select d.testId,
  d.rowId,
  max(if(f.keyName='voltage',f.keyValue,NULL)) as 'voltage',
  max(if(f.keyName='temperature',f.keyValue,NULL)) as 'temperature',
  max(if(f.keyName='velocity',f.keyValue,NULL)) as 'velocity' 
from tests t  
inner join data d 
  on t.testId = d.testId  
inner join data c 
  on t.testId = c.testId 
  and c.rowId = d.rowId  
join data f 
  on f.testId = t.testId 
  and f.rowId = d.rowId  
where (d.keyName = 'voltage' and d.keyValue < 5) 
  and (c.keyName = 'temperature' and c.keyValue = 30) 
  and (t.testType = 'testType1')
GROUP BY d.testId, d.rowId

実際のデータ構造は元の質問には示されていませんが、注意してください。これは、次のように統合できるようです。

select d.testid,
  d.rowid,
  max(case when d.keyName = 'voltage' and d.keyValue < 5 then d.keyValue end) voltage,
  max(case when d.keyName = 'temperature' and d.keyValue =30 then d.keyValue end) temperature,
  max(case when d.keyName = 'velocity' then d.keyValue end) velocity
from tests t
left join data d
  on t.testid = d.testid
group by d.testid, d.rowid

SQL Fiddle with Demoを参照してください。これにより、dataテーブルへの結合が 1 つだけの結果が得られます。

| TESTID | ROWID | VOLTAGE | TEMPERATURE | VELOCITY |
-----------------------------------------------------
|      1 |     1 |       4 |          30 |       20 |
|      1 |     2 |       4 |          30 |       21 |
|      2 |     1 |       4 |          30 |       30 |
|      2 |     2 |       4 |          30 |       31 |
于 2013-03-24T21:51:44.920 に答える