2013-07-15 18 views
0
SELECT 
    `s1`.`question`, 
    GROUP_CONCAT(QUOTE(`so1`.`name`)) `answers` 
FROM 
    `survey` `s1` 
INNER JOIN 
    `survey_option` `so1` 
ON 
    `so1`.`survey_id` = `s1`.`id` 
GROUP BY 
    `s1`.`id`; 

此查詢將產品question列表以answer作爲帶引號的逗號分隔字符串。如何展開GROUP_CONCAT值?

如何將答案字符串展開到數組中?

我想到的第一件事是explode("','", mb_substr($answers_str, 1, -1))

是否有任何我應該注意的陷阱?

+1

不要分組! – Strawberry

+5

如果你不想這樣,你爲什麼要使用GROUP_CONCAT()? – fancyPants

+0

您可以在單行中檢索它,並且可以在客戶端再次分割它@fancyPants – DevZer0

回答

0

我讓這個問題聽起來比實際上更難。我的解決方案並不直接回答我的問題,儘管它解決了潛在的問題。

我需要爲報告門戶網站生成一個數據導出,其中有一組定義的變量(例如first_name,last_name等)+數據變量在整個時間段內變化(即必須包含或排除依賴關於它是否存在於定義的時間間隔中)。此外,它必須以Excel友好格式(例如csv)生成(因此首次嘗試使用逗號使用GROUP CONCATination)。

我去的解決方案是動態查詢生成

public function getCombined/*[..]*/ (array $filter = []) { 
    // Find the columns 
    $freeform_data = $this->db 
     ->prepare(" 
     SELECT 
      DISTINCT `dpd1`.`name` 
     FROM 
      `device_product` `dp1` 
     INNER JOIN 
      `device_product_data` `dpd1` 
     ON 
      `dpd1`.`device_product_id` = `dp1`.`id`; 
     ") 
     ->execute([$filter) 
     ->fetchAll(\PDO::FETCH_COLUMN); 

    $freeform_data_selectors = ''; 
    $freeform_data_join = ''; 

    foreach ($freeform_data as $i => $name) { 
     if ($name != preg_replace('/[^a-z_-]/i', '', $name)) { 
      throw new \ErrorException('Invalid freeform data input name ("' . $name . '").'); 
     } 

     $alias = '`dpd' . ($i + 1) . '`'; 

     $freeform_data_selectors .= ', ' . $alias . '.`value` `freeform_' . $name . '`'; 

     $freeform_data_join .= ' 
     LEFT JOIN 
      `device_product_data` ' . $alias . ' 
     ON 
      ' . $alias . '.`device_product_id` = `dp1`.`id` AND 
      ' . $alias . '.`name` = \'' . $name . '\' 
      '; 
    } 

    $stmt = $this->db 
     ->prepare(" 
     SELECT 
      `d1`.`mac_address` `device_mac_address`,    
      {$freeform_data_selectors} 
     FROM 
      `device_product` `dp1`   
     {$freeform_data_join} 
     GROUP BY 
      `dp1`.`id`;", [\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => false]) 
     ->execute($filter); 

    return stmt; 
} 

這是一個減少的例子,它可能看起來類似於羅賓卡斯特林建議的。但是,實際查詢還有10個連接和一個大型數據集(2M +)。 Castlin的建議將需要更多資源來檢索數據並對其進行組織。

0
# Run query 
SELECT 
# `s1`.`id`, 
    `s1`.`question`, 
    `so1`.`name` 
FROM 
    `survey` `s1` 
INNER JOIN 
    `survey_option` `so1` 
ON 
    `so1`.`survey_id` = `s1`.`id` 

# Fetch query 
$arr = array(); 
while($row = mysql_fetch_object($query)) 
    $arr[$row->question][] = $row->name; 

# If question's aren't unique, you can also fetch 'id' in query and: 
$arr = array(); 
while($row = mysql_fetch_object($query)) 
    $arr[$row->id][] = $row; 

這假設您將查詢值保存爲$query。如果您打算在事後分割它們,則無需執行GROUP_CONCAT。只需使用一個數組,它的關鍵值就足夠了。

+0

在我的情況下,該系統旨在生成基於動態長度用戶輸入的數據報告。數據使用與示例中相同的模式進行存儲。對數據進行後處理本身不會起作用,或者至少沒有任何有效的方式。 – Gajus

+0

恐怕我不明白你的意思。我考慮了這個例子,它應該有相同的數據結構。爲什麼這樣做效率不高? –