2012-10-18 80 views
0

我正在編寫一個存儲過程,它將根據酒類和工作號顯示是/否計數。我開始通過工會來編程當前的類別 - 葡萄酒,啤酒,威士忌 - 但除此之外,可能會有更多的類別,並且我將這些代碼視爲體積龐大。是否可以在一個循環中執行一個聯合,然後傳遞酒精類別參數?託運互聯網,並看到很少關於這個問題,所以任何幫助或指導將不勝感激。在Union中循環全部

我的代碼的開始...

delimiter $$ 
create procedure alc_cat_yn (in jid int) 
begin 
select 
cast(concat(jobid,' - Wine') 
as char(50)) as `Job Number - Consumed Yesterday` 
,sum(case when wine_id=1 then 1 else 0 end) as y 
,sum(case when wine_id=2 then 1 else 0 end) as n 
from demos 
where jobid=jid 
group by jobid 
union all 
select 
cast(concat(jobid,' - Beer') 
as char(50)) as `Job Number - Consumed Yesterday` 
,sum(case when beer_id=1 then 1 else 0 end) as y 
,sum(case when beer_id=2 then 1 else 0 end) as n 
from demos 
where jobid=jid 
group by jobid 
union all 
select 
cast(concat(jobid,' - Whisky') 
as char(50)) as `Job Number - Consumed Yesterday` 
,sum(case when whisky_id=1 then 1 else 0 end) as y 
,sum(case when whisky_id=2 then 1 else 0 end) as n 
from demos 
where jobid=jid 
group by jobid; 
end 
+1

您在這裏遇到困難的原因是您的模式未正確歸一化。 'demos'表中不應該有特定的'wine_id','beer_id'和'whisky_id'列。你在工作和酒精類別之間有多對多的關係,你可以通過互聯網尋找技術來正確標準化。 –

回答

0

從理論上講,你可以有一個循環,用於構建在一個循環中查詢字符串並執行它作爲一個準備好的聲明。但是,這樣做是不好的做法。相反,你應該避免爲不同的酒精類別設置不同的列。使用多行的單列。每行將包含jobid,酒類和一個值(例如1或2)。

我有點迷惑,爲什麼你的列被稱爲*_id,因爲你似乎存儲了一些yes/no信息,而不是另一個表中某行的標識符。你可能想選擇一個不太令人誤解的名字。

對於該類別,您可以使用enum或存儲在字符串中的名稱,也可以使用引用某個其他表的主鍵的數字,該表列出了您的種類。 enum將意味着每個新類別都需要更改數據庫模式。字符串可能會消耗大量的內存,特別是如果您選擇長名稱。因此,引用另一張表格是最靈活的解決方案,從長遠來看可能是您的最佳選擇。

您仍然可以基於擴展表提供當前結構作爲視圖。如果您爲重構的表使用新名稱,併爲該視圖重新使用當前名稱,則可以保持與現有代碼的向後兼容性。

小注:MySQL使用0或1來表示布爾值。所以不要寫case when foo=bar then 1 else 0 end你可以簡單地寫foo=bar。這會使你的代碼更短。 Otoh,它也會使乍一看更難以閱讀,所以最好在這個用途的某個地方發表評論。