2011-05-24 73 views
0

我有兩個表,如下所示:通過PHP基於Drupal的SQL查詢:計數T1 T2加入

table {node} 
`nid`, `uid`, `type` 
1 1 basketball 
2 1 basketball 
3 1 football 
4 2 football 
5 2 basketball 

table {strato_ticket} 
`tid`, `author_uid`, `purpose`, `active` 
1  1 'Ticket to a basketball game' TRUE 
2  1 'Ticket to a football game' TRUE 
3  2 'Ticket to a football game' FALSE 

我想產生計數每種節點的數量的報告,然後計數每個用戶與該類節點關聯的活動門票的數量。

我的解決方案使用了SQL和PHP的組合:我對每種我感興趣的節點都有一個PHP循環,它簡化了SQL查詢,並將其從'type'轉換爲'purpose',例如

$node_types = array('basketball', 'football'); 
foreach($node_types as $node){ 
    switch($type){ 
    case 'basketball': 
     $purpose = array('Ticket to a basketball node'); 
     break; 
    case 'football': 
     $purpose = array('Ticket to a football game'); 
     break; 
    } 
    $where = " WHERE ({strato_ticket}.`purpose` = '" 
    .implode("' OR {strato_ticket}.`purpose` = '",$purpose)."')"; 

最後,我有麻煩點,SQL查詢。當我只是計算每個用戶所擁有的節點,它工作得很好:

$query = " 
     SELECT uid, count(*) AS nodes_owned 
     FROM {node} WHERE `type` = '$type' 
     GROUP BY uid ORDER BY nodes_owned DESC 
     "; 
    $query = db_query($query); 

output: 
Now displaying info for basketball. 
uid nodes_owned 
1  2 
2  1 
Now displaying info for football. 
uid nodes_owned 
1  1 
2  1 

但現在,我需要對查詢另一個表,strato_ticket,事情變得複雜,我的查詢是沒有出現任何的錯誤返回FALSE(我認爲)。

$query = " 
    SELECT count(*) as tickets 
    FROM {strato_ticket} INNER JOIN (
     SELECT node.uid, count(*) AS nodes_owned 
     FROM {node} WHERE `type` = '$type' 
     GROUP BY uid 
    ) AS {nodecount} 
     ON {strato_ticket}.`author_uid` = {nodecount}.`uid` 
     $where 
     GROUP BY nodecount.uid ORDER BY nodecount.nodes_owned DESC 
     "; 
    $query = db_query($query); 

我對SQL不太好,我不太清楚它是如何被破壞的。可以使用一點幫助?

理想情況下希望看到

uid nodes_owned tickets 
//basketball 
1  2  1 
2  1  0 
//football 
1  1  1 
2  1  0 
+0

我建議了在正確輸入你的SQL進行db_query測試您的查詢在MySQL控制檯(其中的錯誤會立即對你明顯),然後審查Drupal的文檔進行指導()。我不認爲你想要在上面{nodecount}周圍捲曲。 – 2011-05-24 04:50:43

+2

爲了在Drupal中實現最好的數據庫實踐,使用數據庫佔位符(例如%s代替$ type,並重寫$ where構造來完成相同操作)。 – 2011-05-24 04:52:10

+1

另外,不要使用\',這是mysql特定的和不必要的,除非你的列使用保留字。使用別名應該使它更容易:'{strato_ticket} st',然後只是'st.autor_uid'。正如克里斯所說,使用%s佔位符(對於安全非常重要!不僅僅是最佳實踐),而且{}僅對於由Drupal維護的表(例如,如果使用的是數據庫前綴名稱)是必需的。請勿將其用於別名或外部表格。 – Berdir 2011-05-24 07:18:03

回答

0

除了佔位符,我可以去以後,我覺得這個解決它。

$form = array(); 
$node_types = array('basketball','football'); 
// if($user->uid == 1){ 
    $form[$type][] = array('#value'=>"Showing how many of each node type each user owns.".'<br/>'); 
    foreach($node_types as $type){ 
    // Count the number of nodes each user owns of $type. 
    $form[$type][] = array('#value'=>"Now displaying info for $type".'s. <br/>'); 
    switch($type){ 
    case 'basketball': 
     $purpose = array('ticket to a basketball game', 'basketball'); 
    break; 
    case 'football': 
     $purpose = array('ticket to a football game'); 
    break; 
    } 
    $purpose = implode("', '", $purpose); 
    //@todo : Make a temporary table to query against so I'm not hitting node table multiple times. 
    $ticketquery = " 
    SELECT author_uid, purpose, COUNT(*) AS invitees_accepted 
    FROM {strato_ticket} 
    WHERE purpose IN ('$purpose') 
    GROUP BY author_uid, `purpose` 
    "; 
    $nodequery = " 
    SELECT node.uid, count(*) AS nodes_owned, type 
    FROM {node} 
    WHERE `type` IN ('$type') 
    GROUP BY uid, type"; 
    $query = " 
    SELECT * FROM 
    ($nodequery) AS nt 
    JOIN 
    ($ticketquery) AS tt 
    ON nt.uid = tt.author_uid 
    GROUP BY nt.uid ORDER BY nt.nodes_owned DESC 
    "; 

    drupal_set_message('Query is <br/>'.$query); 
    //return; 
    $query = db_query($query); 
    $first = true; 
    while ($rec = db_fetch_object($query)){ 
    if($first){ 
     $form[$type][] = array('#value'=>"And the winner is: ".print_r($rec, true).'<br/>'); 
     $first = false; 
    } 
    else { 
    $form[$type][] = array('#value'=>print_r($rec, true).'<br/>'); 
    } 
    } 
// } 
}