2014-02-27 110 views
1

我是新手,當涉及到MSSQL,並試圖轉換下面的MySQL查詢沒有任何喜悅。我通過ODBC連接到Microsoft SQL Server Management Studio中的MySQL數據庫。這工作很好,非常簡單的查詢工作得很好。然而,下面的查詢稍微複雜一點(可能沒有儘可能優化),我無法使它工作。MySQL到MSSQL查詢翻譯

下面的第一個查詢是原始的MySQL查詢,第二個查詢是我嘗試的MSSQL轉換。

MySQL查詢

SELECT timestamp, `First Name`, `Last Name`, `Email Address`, `Department`, `Case`, `Partner`, `Category`, `Tag Title`, `Question`, `Answer`, 
     MAX(CASE `Secondary Metric Question` WHEN 'Support' THEN `Secondary Metric Question` end) AS 'Metric 1 Title', 
     MAX(CASE `Secondary Metric Question` WHEN 'Support' THEN `Answer` end) AS 'Metric 1 Answer', 
     MAX(CASE `Secondary Metric Question` WHEN 'Completeness' THEN `Secondary Metric Question` end) AS 'Metric 2 Title', 
     MAX(CASE `Secondary Metric Question` WHEN 'Completeness' THEN `Answer` end) AS 'Metric 2 Answer', 
     MAX(CASE `Secondary Metric Question` WHEN 'Policy' THEN `Secondary Metric Question` end) AS 'Metric 3 Title', 
     MAX(CASE `Secondary Metric Question` WHEN 'Policy' THEN `Answer` end) AS 'Metric 3 Answer', 
     `Message`, 
     CASE `Reply Requested` WHEN 1 THEN "YES" ELSE "NO" END AS "Reply Requested", 
     `Response Session` 
    FROM (
     SELECT T0.timestamp, T8.first_name AS 'First Name', T8.last_name AS 'Last Name', T8.email AS 'Email Address', T0.dept AS 'Department', T0.case AS 'Case', T0.partner AS 'Partner', T3.title AS 'Category', T2.title AS 'Question', T2.private_title AS 'Tag Title', T6.title AS 'Secondary Metric Question', T0.answer AS 'Answer', T4.key AS 'Message', T4.reply_requested AS 'Reply Requested', T0.response_session AS 'Response Session' 
       FROM responses AS T0 

        LEFT JOIN qrs_metrics AS T1 
        ON T0.qrs_metric_id = T1.qrs_metric_id 

        LEFT JOIN quick_responses AS T2 
        ON T1.qrs_id = T2.qrs_id 

        LEFT JOIN custom_categories AS T3 
        ON T2.category = T3.original_id AND T3.user_id = T2.user_id 

        LEFT JOIN rre_aggregates AS T4 
        ON T0.comment_id = T4.id 

        LEFT JOIN widget_responses AS T5 
        ON T0.widget = T5.id 

        LEFT JOIN secondary_metrics AS T6 
        ON T1.metric_id = T6.id 

        LEFT JOIN private_messages AS T7 
        ON T4.id = T7.comment_id AND T7.type = 3 

        LEFT JOIN users AS T8 
        ON T2.user_id = T8.user_id 

        WHERE T0.timestamp >= '2014-02-17 00:00:00' 
        AND T0.qrs_metric_id = T1.qrs_metric_id 

    ) tmp_table 
    GROUP BY `Response Session` 

MSSQL翻譯嘗試

SELECT [timestamp], [First Name], [Last Name], [Email Address], [Department], [Case], [Partner], [Category], [Tag Title], [Question], [Answer], 
     MAX(CASE [Secondary Metric Question] WHEN 'Support' THEN [Secondary Metric Question] end) AS 'Metric 1 Title', 
     MAX(CASE [Secondary Metric Question] WHEN 'Support' THEN [Answer] end) AS 'Metric 1 Answer', 
     MAX(CASE [Secondary Metric Question] WHEN 'Completeness' THEN [Secondary Metric Question] end) AS 'Metric 2 Title', 
     MAX(CASE [Secondary Metric Question] WHEN 'Completeness' THEN [Answer] end) AS 'Metric 2 Answer', 
     MAX(CASE [Secondary Metric Question] WHEN 'Policy' THEN [Secondary Metric Question] end) AS 'Metric 3 Title', 
     MAX(CASE [Secondary Metric Question] WHEN 'Policy' THEN [Answer] end) AS 'Metric 3 Answer', 
     [Message], 
     CASE [Reply Requested] WHEN 1 THEN 'YES' ELSE 'NO' END AS 'Reply Requested', 
     [Response Session] 
    FROM (
     SELECT T0.[timestamp], T8.first_name AS 'First Name', T8.last_name AS 'Last Name', T8.email AS 'Email Address', T0.dept AS 'Department', T0.[case] AS 'Case', T0.partner AS 'Partner', T3.title AS 'Category', T2.title AS 'Question', T2.private_title AS 'Tag Title', T6.title AS 'Secondary Metric Question', T0.answer AS 'Answer', T4.[key] AS 'Message', T4.reply_requested AS 'Reply Requested', T0.response_session AS 'Response Session' 
       FROM AZUREMYSQL...responses AS T0 

        LEFT JOIN AZUREMYSQL...qrs_metrics AS T1 
        ON T0.qrs_metric_id = T1.qrs_metric_id 

        LEFT JOIN AZUREMYSQL...quick_responses AS T2 
        ON T1.qrs_id = T2.qrs_id 

        LEFT JOIN AZUREMYSQL...custom_categories AS T3 
        ON T2.category = T3.original_id AND T3.user_id = T2.user_id 

        LEFT JOIN AZUREMYSQL...rre_aggregates AS T4 
        ON T0.comment_id = T4.id 

        LEFT JOIN AZUREMYSQL...widget_responses AS T5 
        ON T0.widget = T5.id 

        LEFT JOIN AZUREMYSQL...secondary_metrics AS T6 
        ON T1.metric_id = T6.id 

        LEFT JOIN AZUREMYSQL...private_messages AS T7 
        ON T4.id = T7.comment_id AND T7.type = 3 

        LEFT JOIN AZUREMYSQL...users AS T8 
        ON T2.user_id = T8.user_id 

        WHERE T0.timestamp >= '2014-02-17 00:00:00' 
        AND T0.qrs_metric_id = T1.qrs_metric_id 

    ) tmp_table 
    GROUP BY [Response Session] 

的當前錯誤,我在SSMS receiveing是

Column 'tmp_table.timestamp' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause. 

如果任何人都可以幫幫忙我會[R真的很感激。

謝謝

回答

1

您需要在GROUP BY中包含所有不屬於聚合的列。

編輯:無法使用DISTINCT在這裏,也許與嵌套選擇,但GROUP BY將做得很好。

+0

使用'DISTINCT'會導致以下錯誤'關鍵字'DISTINCT'附近的語法錯誤'。我會將其餘列添加到'GROUP BY',看看會發生什麼。你能看到我的查詢有任何其他問題嗎? – superphonic

+0

DISTINCT必須先放在第一位。不要看到其他任何不適用於MSSQL的東西。 – Shikiju

+0

棒上的廢話,將其他列添加到「GROUP BY」工作!真的認爲我的翻譯很順利,而且這個錯誤是第一個排在第一位的。輝煌。謝謝您的幫助。 – superphonic

0
<pre> 
I have developed a custom php script to convert mysql to mssql query for one of my project. Hope it helps some one. 

$query = "SELECT 
       t.transaction_id,t.cust_payment_id, t.amount,count(t.transaction_id), 
       t.transaction_type as T1Trans,t2.transaction_type as T2Trans,t.gw_date as T1Date,t2.gw_date as T2Date, t2.description 
      FROM pga_transaction t use index(txn_cleared), pga_transaction t2 
      WHERE t.cleared = 0 
      AND  t.cust_payment_id = t2.cust_payment_id 
      AND  t.transaction_type IN ('Authorized','Refunded') 
      AND  t2.transaction_type IN ('Authorized','Refunded') 

      AND  t.cust_payment_id in (34650806) 
      AND  t2.cust_payment_id in (34650806) 
      GROUP BY t.transaction_type, t.cust_payment_id,t2.cust_payment_id 
      ORDER BY t.date_created"; 

Call ModmodifyQuery($query); 

function modifyQuery($query) 
    { 

       $query = str_replace("`", "", $query); 
       /*Order By functionality starts*/ 
       $unixTimeString = ''; 
       preg_match_all("#order[\s]by[^\w]{1,}([0-9]{1,})([\,]{0,})([0-9]{0,})#i",$query,$orderByNum); 

       if(!empty($orderByNum[0])) 
       { 
       $selectList = $this->selectList($query,"SELECT","FROM"); 
       $orderByList = $this->orderByList($query,"ORDER BY","DESC"); 

       $selectList = $this->sqlParser($selectList); 

       $selectList = preg_replace('#[\s]as[\s]\w*#i', " ", $selectList); 
       $orderByArr = explode(",",$orderByList); 
       $orderByArr = array_map('trim',$orderByArr); 
       /**Code for gropup by 1*/ 
       if(!empty($orderByNum[0])) 
       { 
        $orderByCol=array(); 
        foreach($orderByArr as $colno) 
        { 
           $orderByCol[]=$selectList[$colno-1]; 
        } 
       } 
       if(!empty($orderByNum[0])) 
       { 
        $orderBy = implode(",",$orderByCol); 
       } 

       if(stripos($query, "ORDER BY")) 
       { 
        $query = preg_replace('#order[\s]by[^\w]{1,}([0-9]{1,})([\,]{0,})([0-9]{0,})([\,]{0,})([0-9]{0,})([\,]{0,})([0-9]{0,})([\,]{0,})([0-9]{0,})([\,]{0,})([0-9]{0,})([\,]{0,})([0-9]{0,})([\,]{0,})([0-9]{0,})([\,]{0,})([0-9]{0,})#i', "ORDER BY $orderBy ", $query);      
       } 
       } 
      /*Ends here*/ 
      /*Group By functionality starts*/ 
      preg_match_all("#group[\s]by\s#i",$query,$groupByWord); 
      preg_match_all("#group[\s]by[^\w]{1,}([0-9]{1,})([\,]{0,})([0-9]{0,})#i",$query,$groupByNum); 
      $groupBy = !empty($groupByWord[0])?$groupByWord[0]:$groupByNum[0]; 
      if(!empty($groupBy)) 
      { 
      $selectList = $this->selectList($query,"SELECT","FROM"); 
      $groupByList = $this->groupByList($query,"GROUP BY","ORDER BY"); 
      $selectList = $this->sqlParser($selectList); 
      $selectList = preg_replace('#[\s]as[\s]\w*#i', " ", $selectList); 
      $groupByArr = explode(",",$groupByList); 

      $groupByArr = array_map('trim',$groupByArr); 
      /**Code for gropup by 1*/ 
      if(!empty($groupByNum[0])) 
      { 
       $groupByCol=array(); 
       foreach($groupByArr as $colno) 
       { 

         $groupByCol[]=$selectList[$colno-1]; 
       } 
      } 
      /*End here*/ 
      if(!empty($groupByNum[0])) 
      { 
       $groupBy = implode(",",$groupByCol); 
      } 
      else 
      { 
       $combineVal = array_merge_recursive($groupByArr,$selectList);  
       $combineVal = array_map('trim',$combineVal); 
       $combineVal = array_unique($combineVal); 
       $groupBy = implode(",",$combineVal); 
      } 
      $trimmed_array=array_map('trim',$groupByArr); 
      if(stripos($query, "ORDER BY")) 
      { 
       $query = preg_replace('#GROUP BY[\s\S]+?ORDER BY#i', "GROUP BY $groupBy ORDER BY ", $query); 
      } 
      else 
      { 
       $query = preg_replace('#GROUP BY[\s].*#i', "GROUP BY ".$groupBy, $query); 
      } 
      } 

      /*Group By functionality ends*/ 
      preg_match_all("#\sforce[\s]*index[\s]*\(\w*\)[\s]*#i",$query,$forceIndex); 
      if(!empty($forceIndex['0']['0'])) 
      { 
       $forceString = $forceIndex['0']['0'].')'; 
       $forceString = str_ireplace('force index','WITH (index',$forceString); 
      } 

      preg_match_all("#UNIX_TIMESTAMP(\h*\([^)]*?[^)]*?\))#i",$query,$unixTimeIndex); 
      if(!empty($unixTimeIndex['0']['0'])) 
      { 
       $unixTimeString = rtrim($unixTimeIndex['0']['0'],')'); 
       $unixTimeString = str_ireplace('UNIX_TIMESTAMP(','',$unixTimeString); 
      } 

      // Group By function call 
      //replace Limit keyword with TOP keyword 
      preg_match_all("#LIMIT[^\w]{1,}([0-9]{1,})([\,]{0,})([0-9]{0,})#",$query,$matches); 
      if(!empty($matches[1][0])) 
      $query = str_ireplace("SELECT ", "SELECT TOP ".$matches[1][0]." ", $query); 


      $patterns[0] = '#FROM_UNIXTIME\(([^/]{0,})\)#i';//replace From UnixTime command in MS-Sql, doesn't work 
      $patterns[1] = '#LIMIT[^\w]{1,}([0-9]{1,})([\,]{0,})([0-9]{0,})#i'; 
      $patterns[2] = '#now\([\s]*#i';// Now() function should be replaced with getutcdate() 
      $patterns[3] = '#DATE_FORMAT[\s]*\([\s]*#i';// date_format() function should be replaced with format 
      $patterns[4] = '#[\s]*(%Y{1}-%m{1}-%d{1})#i';// Change '%Y-%m-%d' patteren to 'yyyy-MM-dd' 
      $patterns[5] = '#%m{1} %d{1}#i';// Change '%m %d' patteren to 'MM dd' \' 
      $patterns[6] = '#datediff\([\s]*#i';// datediff() function accepts 3 parameters 
      $patterns[7] = '#RAND\(#i'; 
      $patterns[8] = '#WHERE 1#i';// where 1 should be replaced with WHERE 1=1 
      $patterns[9] = '#IF[\s]*\([\s]*#i';// IF should be replaced with where IIF 
      $patterns[10] = '#CHARACTER_LENGTH\(#i';//CHARACTER_LENGTH() function should be replaced with LENGTH() 

      $patterns[11] ='#\%M{1}[\s]*/[\s]*\%Y{1}#i';// Mysql Date: November/2017 is changed to November, 2017 
      $patterns[12] ='#[\s]DATE\([\s]*#i';// Mysql Date() is changed to CONVERT (date,GETDATE()) 
      $patterns[13] ='#[\s]DATE_ADD\([\s]*#i';// Mysql Date() is changed to CONVERT (date,GETDATE()) 
      $patterns[14] ='#\,[\s]*INTERVAL 1 DAY[\s]*#i';// INTERVAL 1 DAY is replaced with '' 
      //$patterns[16] ='#\sforce\s#i';// INTERVAL 1 DAY is replaced with '' 
      $patterns[15] ='#\sforce index[\s]*\(\w*\)[\s]*#i';// INTERVAL 1 DAY is replaced with '' 
      //$patterns[16] ='#\sforce\s#i';// INTERVAL 1 DAY is replaced with '' 
      //index\([\s]*\w*\) 
      $patterns[16] ='#\ssecure_pgatxn.?#i'; 
      $patterns[17] ='#\ssecure_pga.?#i'; 
      $patterns[18] ='#\sIFNULL#i'; 
      $patterns[19] ='#[\s]*&&{1}[\s]*#i'; 
      //$patterns[20] ='#unix_timestamp[\s]*\([\s]*.*[\w]*\)#i'; 
      $patterns[20] ='#unix_timestamp(\h*\([^)]*?[^)]*?\))#i'; 

      // Replacement Queries 
      $replacements[0] = 'getdate()'; 
      $replacements[1] = ''; 
      $replacements[2] = 'getutcdate('; 
      $replacements[3] = 'FORMAT('; 
      $replacements[4] = 'yyyy-MM-dd'; 
      $replacements[5] = 'MM dd'; 
      $replacements[6] = 'datediff(DAY,'; 
      $replacements[7] = 'NEWID('; 
      $replacements[8] = 'WHERE 1=1'; 
      $replacements[9] = 'IIF('; 
      $replacements[10] = 'LENGTH('; 
      // $replacements[11] = '\\1'; //datediff(ss, '1970-01-01', SYSDATETIMEOFFSET()) 
      $replacements[11] = 'Y'; 
      $replacements[12] = ' CONVERT(date,'; 
      $replacements[13] = ' DATEADD(DAY,1,'; 
      $replacements[14] = ''; 
      $replacements[15] = isset($forceString)?$forceString:''.' '; 
      $replacements[16] = ' '; 
      $replacements[17] = ' '; 
      $replacements[18] = ' ISNULL'; 
      $replacements[19] = ' AND '; 
      $replacements[20] = "DATEDIFF(s, '1970-01-01 00:00:00',". $unixTimeString.")"; 

      $query = preg_replace($patterns, $replacements, $query); 
      //echo $query;exit; 
      return $query; 
    } 

function selectList($string, $start, $end){ 
     $string = ' ' . $string; 
     $ini = stripos($string, $start); 
     if ($ini == 0) return ''; 
     $ini += strlen($start); 
     $len = stripos($string, $end, $ini) - $ini; 

     return substr($string, $ini, $len); 
    } 
    function groupByList($string, $start, $end){ 

     $string = ' ' . $string; 
     $ini = stripos($string, $start); 
     if ($ini == 0) return ''; 
     $ini += strlen($start); 

     if(stripos($string, "ORDER BY") === false) 
     { 
      return substr($string, $ini); 
     } 
     else 
     { 
      $len = stripos($string, $end, $ini) - $ini; 
      return substr($string, $ini, $len); 
     } 
    } 
    function orderByList($string, $start, $end){ 

     $string = ' ' . $string; 
     $ini = stripos($string, $start); 
     if ($ini == 0) return ''; 
     $ini += strlen($start); 

     if(stripos($string, "DESC") === false) 
     { 
      return substr($string, $ini); 
     } 
     else 
     { 
      $len = stripos($string, $end, $ini) - $ini; 
      return substr($string, $ini, $len); 
     } 
    } 

    function sqlParser($str) 
    { 
     $str = str_split($str); 
      $tokens = array(); 
      $token = ""; 
      $stack = array(); 
      foreach($str as $char) { 
       if($char == "," && empty($stack)) { 
        $tokens[] = trim($token); 
        $token = ""; 
       } else { 
        $token = $token .$char; 
        if($char == '(') { 
         array_unshift($stack, $char); 
        } 

        if($char == ')') { 
         array_shift($stack); 
        } 
       } 

       //echo "<br>".$char; 
      } 

      $tokens[] = trim($token); 
      return $tokens; 
    } 
</pre>