[英]How do I create a view off a property value table in SQL
我在SQL中有一個具有四列的表。 其中兩個是屬性和值列,用於存儲我們一台服務器的性能指標。 我們一直在不斷提出新的性能指標,並且我們不想一直重新設計架構,所以這就是為什么我們以這種方式設計表格。
麻煩的是,當我創建一個視圖來查看表時,好像它已正確歸一化一樣,我得到一個查詢,它只大喊“哦,我的天哪,這是廢話”,因為它涉及到一個與表連接12次的表。 這是我用於視圖的查詢。
基本上,感覺好像我做錯了什么,但是我找不到解決該問題的更好方法。
SELECT
astats.AQTORStatsID,
astats.ServerName,
astats.Remarks,
astats.StatsBeginDateTime,
astats.StatsEndDateTime,
asi1.AQTORStatValue as 'QtCPU_Average',
asi2.AQTORStatValue as 'QtCPU_TopQuintile',
asi3.AQTORStatValue as 'QtCPU_TopOnePercent',
asi4.AQTORStatValue as 'QtCl_Average',
asi5.AQTORStatValue as 'QtCl_TopQuintile',
asi6.AQTORStatValue as 'QtCl_TopOnePercent',
asi7.AQTORStatValue as 'UpdPrcStd_Average',
asi8.AQTORStatValue as 'UpdPrcStd_TopQuintile',
asi9.AQTORStatValue as 'UpdPrcStd_TopOnePercent',
asi10.AQTORStatValue as 'RcRsUPr_Average',
asi11.AQTORStatValue as 'RcRsUPr_TopQuintile',
asi12.AQTORStatValue as 'RcRsUPr_TopOnePercent'
FROM
tb_rAQTORStatsItem asi1
INNER JOIN tb_rAQTORStatsItem asi2 ON asi1.AQTORStatsID = asi2.AQTORStatsID
INNER JOIN tb_rAQTORStatsItem asi3 ON asi2.AQTORStatsID = asi3.AQTORStatsID
INNER JOIN tb_rAQTORStatsItem asi4 ON asi3.AQTORStatsID = asi4.AQTORStatsID
INNER JOIN tb_rAQTORStatsItem asi5 ON asi4.AQTORStatsID = asi5.AQTORStatsID
INNER JOIN tb_rAQTORStatsItem asi6 ON asi5.AQTORStatsID = asi6.AQTORStatsID
INNER JOIN tb_rAQTORStatsItem asi7 ON asi6.AQTORStatsID = asi7.AQTORStatsID
INNER JOIN tb_rAQTORStatsItem asi8 ON asi7.AQTORStatsID = asi8.AQTORStatsID
INNER JOIN tb_rAQTORStatsItem asi9 ON asi8.AQTORStatsID = asi9.AQTORStatsID
INNER JOIN tb_rAQTORStatsItem asi10 ON asi9.AQTORStatsID = asi10.AQTORStatsID
INNER JOIN tb_rAQTORStatsItem asi11 ON asi10.AQTORStatsID = asi11.AQTORStatsID
INNER JOIN tb_rAQTORStatsItem asi12 ON asi11.AQTORStatsID = asi12.AQTORStatsID
INNER JOIN tb_dAQTORStats astats on asi12.AQTORStatsID = astats.AQTORStatsID
WHERE
asi1.AQTORStatName = 'QtCPU_Average'
AND asi2.AQTORStatName = 'QtCPU_TopQuintile'
AND asi3.AQTORStatName = 'QtCPU_TopOnePercent'
AND asi4.AQTORStatName = 'QtCl_Average'
AND asi5.AQTORStatName = 'QtCl_TopQuintile'
AND asi6.AQTORStatName = 'QtCl_TopOnePercent'
AND asi7.AQTORStatName = 'UpdPrcStd_Average'
AND asi8.AQTORStatName = 'UpdPrcStd_TopQuintile'
AND asi9.AQTORStatName = 'UpdPrcStd_TopOnePercent'
AND asi10.AQTORStatName = 'RcRsUPr_Average'
AND asi11.AQTORStatName = 'RcRsUPr_TopQuintile'
AND asi12.AQTORStatName = 'RcRsUPr_TopOnePercent'
恕我直言,這種代碼(以及麻煩的設計索引)是您為“屬性表”這一慣用語的靈活性而付出的代價的一部分-您付錢,然后就選擇了!-)
這是您的操作方式:
SELECT
astats.AQTORStatsID
, astats.ServerName
, astats.Remarks
, astats.StatsBeginDateTime
, astats.StatsEndDateTime
, QtCPU_Average = max(case when asi.AQTORStatName = 'QtCPU_Average' then asi.AQTORStatValue end)
, QtCPU_TopQuintile = max(case when asi.AQTORStatName = 'QtCPU_TopQuintile' then asi.AQTORStatValue end)
, QtCPU_TopOnePercent = max(case when asi.AQTORStatName = 'QtCPU_TopOnePercent' then asi.AQTORStatValue end)
, QtCl_Average = max(case when asi.AQTORStatName = 'QtCl_Average' then asi.AQTORStatValue end)
, QtCl_TopQuintile = max(case when asi.AQTORStatName = 'QtCl_TopQuintile' then asi.AQTORStatValue end)
, QtCl_TopOnePercent = max(case when asi.AQTORStatName = 'QtCl_TopOnePercent' then asi.AQTORStatValue end)
, UpdPrcStd_Average = max(case when asi.AQTORStatName = 'UpdPrcStd_Average' then asi.AQTORStatValue end)
, UpdPrcStd_TopQuintile = max(case when asi.AQTORStatName = 'UpdPrcStd_TopQuintile' then asi.AQTORStatValue end)
, UpdPrcStd_TopOnePercent = max(case when asi.AQTORStatName = 'UpdPrcStd_TopOnePercent' then asi.AQTORStatValue end)
, RcRsUPr_Average = max(case when asi.AQTORStatName = 'RcRsUPr_Average' then asi.AQTORStatValue end)
, RcRsUPr_TopQuintile = max(case when asi.AQTORStatName = 'RcRsUPr_TopQuintile' then asi.AQTORStatValue end)
, RcRsUPr_TopOnePercent = max(case when asi.AQTORStatName = 'RcRsUPr_TopOnePercent' then asi.AQTORStatValue end)
from tb_dAQTORStats astats
join tb_rAQTORStatsItem asi on asi.AQTORStatsID = astats.AQTORStatsID
group by
astats.AQTORStatsID
, astats.ServerName
, astats.Remarks
, astats.StatsBeginDateTime
, astats.StatsEndDateTime
筆記:
一個具有列模式或矩形編輯功能的優秀文本編輯器確實可以幫助解決此類問題。 我想到了UltraEdit或Emacs。 我大約在一分鍾內在UltraEdit中創建了上面的代碼。
如果缺少一種類型的讀取,則使用INNER JOIN的原始查詢將刪除給定服務器的所有讀取。 不好。 對於具有至少一個讀數的任何服務器,此查詢將為每個服務器返回一行。 如果要返回所有服務器,無論是否有任何讀數,請將INNER JOIN更改為LEFT JOIN。
除非您需要通過外鍵強制執行數據完整性,否則您不需要為統計信息名稱使用單獨的表。
有一個包含所有可能的統計信息名稱的表(我想無論如何都應該具有,其中包含tb_rAQTORStatsItem的fkey約束)
然后,您可能會遇到類似:
SELECT astats.QTORStatsID, astats.ServerName, astats.Remarks,
astats.StatsBeginDateTime, astats.StatsEndDateTime,
max(case item.AQTORStatName when 'QtCPU_Average' then AQTORStatValue end) as QtCPU_Average,
max(case item.AQTORStatName when 'QtCPU_TopQuintile' then AQTORStatValue end) as QtCPU_TopQuintile,
/* repeat for each statistic... */
FROM tb_dAQTORStats astats
CROSS JOIN tb_rAQTORStatNames statnames
LEFT JOIN tb_rAQTORStatsItem item
ON item.AQTORStatName = statnames.AQTORStatName
AND item.AQTORStatsID = astats.AQTORStatsID
GROUP BY astats.QTORStatsID, astats.ServerName, astats.Remarks,
astats.StatsBeginDateTime, astats.StatsEndDateTime
盡管這仍然很丑陋,但至少您可以將N向聯接剪成3向聯接。 是的,這是一種靈活性和簡單性的案例。 添加列是解決問題的一種更整潔的方式,因為數據庫架構將精確匹配您收集的統計信息和它們的類型:但是您需要保持同步。
(nb的查詢語法未經測試,我假設CROSS JOIN以我期望的方式工作)
這種設計大約是從關系型設計到純EAV(實體-屬性-值)設計的一半。 是的,它們對於SQL數據庫來說具有一些令人毛骨悚然的方面。對於我發現的這個問題,最好的解決方案是使用多維數據集和/或數據透視表,而不是嘗試將這種圓釘釘入關系視圖的方孔中。
您可以使用適合的功能:SSAS,Reporting Services數據透視報表,甚至Excel數據透視表。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.