2014-06-18 88 views
0

我有一個包含年齡,性別,sid和目標名稱的表。我想按年齡/性別對此進行分組,然後顯示每個年齡/性別的前2個最常用目標名稱的值。如何在MySQL聲明/查詢中動態創建CASE語句

這裏的示例表:

Sample Table MySQL Table 1

我已成功使用查詢得到一個輸出:

SELECT age, gender, 
SUM(CASE WHEN sid = 'Frank.net Life Cover' THEN 1 ELSE 0 END) AS 'Frank.net Life Cover', 
SUM(CASE WHEN sid = 'Frank.net Salary Protection' THEN 1 ELSE 0 END) AS 'Frank.net Salary Protection', 
SUM(CASE WHEN sid = 'Frank.net Hospital Cash Back' THEN 1 ELSE 0 END) AS 'Frank.net Hospital Cash Back' 
FROM (SELECT uid, sid, goalname, gender, age 
     FROM sampletable 
     WHERE age >=16 
     AND age < 100 
     GROUP BY age, gender); 

這裏的輸出:

Sample MySQL Table 2

我期望的輸出有點像這但關於這一點的事情是它不是動態的。新的目標名稱被添加,這將不適用,因爲我手動將目標名稱放在CASE語句中。另外,我只需要顯示每個年齡/性別的最常用的2個目標名稱。

注意:如果您無法顯示排名前2並且只顯示每個目標名稱的總數,則可以。我想我可以通過比較PHP中每個目標名稱的總數來得到前兩名。我只需要有一個動態的SQL查詢。

謝謝!

+1

您發佈的SQL數據作爲畫面每一次,一隻小貓死了。使用[小提琴](http://sqlfiddle.com) –

+0

對不起。我不知道這件事。我試圖在SQLFiddle上覆制它,但是我有一個錯誤:http://sqlfiddle.com/#!2/9cc8fa – maikelsabido

+0

如果sqlfiddle有問題(它發生),那麼只需粘貼爲問題文本(意味着它很容易複製和實驗)。 – Kickstart

回答

1

的問題是,你會用不同的列數,這是雜亂的過程(而且可能更容易使每個回爲一個不同的行反正)

它會降落了可以使用PHP動態建立查詢,但我不想這樣做在現場的情況: -

<?php 

$sql = "SELECT DISTINCT goalname FROM sampletable"; 

if ($result = $mysqli->query($sql)) 
{ 
    $sum_col = array(); 
    while ($row = $result->fetch_row()) 
    { 
     $sum_col[] = "SUM(CASE WHEN goalname= '".$mysqli->real_escape_string($row['goalname'])."' THEN 1 ELSE 0 END) AS '".$mysqli->real_escape_string($row['goalname'])."'" 
    } 

    if (count($sum_col) > 0) 
    { 
     $sql = "SELECT age, 
        gender, 
        ".implode(",", $sum_col)." 
        FROM sampletable 
        WHERE age >=16 
        AND age < 100 
        GROUP BY age, gender"; 

     if ($result = $mysqli->query($sql)) 
     { 
     } 
    } 
} 
?> 

不過,我會建議它會更容易,只是做了簡單的分組選擇和排序之後格式化: -

SELECT age, 
    gender, 
    goalname, 
    COUNT(*) 
FROM sampletable 
WHERE age >=16 
AND age < 100 
GROUP BY age, gender, goalname 

,或者如果你需要每一個目標的名字的每個人,不論他們選擇與否: -

SELECT age, 
    gender, 
    sub0.goalname, 
    COUNT(sampletable.sid) 
FROM (SELECT DISTINCT goalname FROM sampletable) sub0 
LEFT OUTER JOIN sampletable 
ON sub0.goalname = sampletable.goalname 
WHERE age >=16 
AND age < 100 
GROUP BY age, gender, sub0.goalname 

獲取頂部2是更復雜一點,只是在邏輯上是不可能的與你當前的輸出(因爲列將指不同的行)

編輯 - 獲得最高的2對夫婦是這樣做的,但兩個計數在1列(用##分隔) - 改變這個東西你的目標名字可以從不包含): - 此

SELECT age, gender, SUBSTRING_INDEX(GROUP_CONCAT(CONCAT_WS('=', goalname, goalcount) ORDER BY goalcount DESC SEPARATOR '##'), '##', 2) 
FROM 
(
    SELECT age, 
     gender, 
     goalname, 
     COUNT(sid) AS goalcount 
    FROM user 
    WHERE age >=16 
    AND age < 100 
    GROUP BY age, gender, goalname 
) sub1 
GROUP BY age, gender; 

SQL小提琴: -

http://sqlfiddle.com/#!9/9cc8f/4

+0

非常感謝你爲這個精心設計的答案。我會嘗試這個解決方案。 – maikelsabido

0

最好通過規範化拆分表,並將sid,目標名放入另一個表 ,並將sid用作主表中的外鍵。這樣您就可以從其他表中動態檢查值而不是對它們進行硬編碼。

SELECT s.age, s.gender, count(s.sid),p.goalname 
FROM sampletable s,proposedtable p 
where s.sid=p.sid and s.age >=16 AND s.age < 100 
group by s.age,s.gender