2010-08-18 19 views
1

我有一個表格,格式如下。創建一個查詢的摘要結果

mysql> describe unit_characteristics; 
+----------------------+------------------+------+-----+---------+----------------+ 
| Field    | Type    | Null | Key | Default | Extra   | 
+----------------------+------------------+------+-----+---------+----------------+ 
| id     | int(10) unsigned | NO | PRI | NULL | auto_increment | 
| uut_id    | int(10) unsigned | NO | PRI | NULL |    | 
| uut_sn    | varchar(45)  | NO |  | NULL |    | 
| characteristic_name | varchar(80)  | NO | PRI | NULL |    | 
| characteristic_value | text    | NO |  | NULL |    | 
| creation_time  | datetime   | NO |  | NULL |    | 
| last_modified_time | datetime   | NO |  | NULL |    | 
+----------------------+------------------+------+-----+---------+----------------+ 

每個uut_sn都有多個特性名/值對。我想用MySQL來生成表格

+----------------------+-------------+-------------+-------------+--------------+ 
| uut_sn | char_name_1 | char_name_2 | char_name_3 | char_name_4 | ...   | 
+----------------------+-------------+-------------+-------------+--------------+ 
| 00000 | char_val_1 | char_val_2 | char_val_3 | char_val_4 | ...   | 
| 00001 | char_val_1 | char_val_2 | char_val_3 | char_val_4 | ...   | 
| 00002 | char_val_1 | char_val_2 | char_val_3 | char_val_4 | ...   | 
| ..... | char_val_1 | char_val_2 | char_val_3 | char_val_4 | ...   | 
+----------------------+------------------+------+-----+---------+--------------+ 

這是可能的只有一個查詢?

感謝, -Peter

回答

3

這是一個標準的支點查詢:

SELECT uc.uut_sn, 
     MAX(CASE 
       WHEN uc.characteristic_name = 'char_name_1' THEN uc.characteristic_value 
       ELSE NULL 
      END) AS char_name_1, 
     MAX(CASE 
       WHEN uc.characteristic_name = 'char_name_2' THEN uc.characteristic_value 
       ELSE NULL 
      END) AS char_name_2, 
     MAX(CASE 
       WHEN uc.characteristic_name = 'char_name_3' THEN uc.characteristic_value 
       ELSE NULL 
      END) AS char_name_3, 
    FROM unit_characteristics uc 
GROUP BY uc.uut_sn 

爲了使動態的,你需要使用MySQL's dynamic SQL syntax called Prepared Statements。它需要兩個查詢 - 第一個獲取characteristic_name值的列表,因此您可以將適當的字符串連接到CASE表達式中,就像您在我的示例中看到的那樣是最終查詢。

+0

+1 Nitpick:'null'是沒有'when'匹配時的默認值,所以你可以省略'else null' – Andomar 2010-08-18 18:30:57

+0

+1來提及動態sql。 – 2010-08-18 19:04:27

+0

感謝您的答案。解決方案和解釋都很好。我不得不選擇@OMG小馬更好地回答我不熟悉表樞軸。 @Bill,我對EAV反模式不熟悉,所以我用Google搜索了一些術語,並且似乎有很多關於這個主題的幻燈片,有沒有帶有音頻的版本?看起來你反對EAV,但是當有很多名稱/值對時會發生什麼?如果有超過200個名稱/值對,將它們翻譯爲列是否有意義? – cfpete 2010-08-18 20:36:08

1

您正在使用EAV反模式。沒有辦法自動生成您所描述的數據透視表,而無需對要包含的特徵進行硬編碼。正如@OMG Ponies提到的那樣,您需要使用動態SQL以自定義方式對查詢進行概括,以獲取要包含在結果中的一組特徵。因爲它們存儲在數據庫中,所以我建議你每行獲取一個特徵,並且如果你希望一個應用程序對象代表具有所有特徵的單個UUT,那麼你編寫代碼來循環遍歷行你在你的應用程序中獲取它們,將它們收集到對象中。

例如在PHP中:

$sql = "SELECT uut_sn, characteristic_name, characteristic_value 
     FROM unit_characteristics"; 
$stmt = $pdo->query($sql); 

$objects = array(); 
while ($row = $stmt->fetch()) { 
    if (!isset($objects[ $row["uut_sn"] ])) { 
     $object[ $row["uut_sn"] ] = new Uut(); 
    } 
    $objects[ $row["uut_sn"] ]->$row["characteristic_name"] 
          = $row["characterstic_value"]; 
} 

這已超過在查詢硬編碼識別名的解決方案的幾個優點:

  • 該解決方案只需要一個SQL查詢,而不是兩個。
  • 構建動態SQL查詢不需要複雜的代碼。
  • 如果您忘記了其中一個特性,該解決方案無論如何都會自動找到它。
  • MySQL中的GROUP BY通常很慢,這樣可以避免GROUP BY。