不尋常的關係,二元方面
我對數據庫有非常不尋常的問題。我不是一個很好的英語演講者,但很好的英語閱讀者:) 所以為了解釋,我會給你例子。
第1部分
在 MySQL 中,我有兩個表的關係我無法像主外鍵一樣執行。向前說,這是一些“一對多”的關係。這是表格的範例:
#1 – States ID ConcVal Type Time 1 14 1 05:30 2 13 1 06:30 3 10 2 07:00 4 13 2 08:50 5 10 2 09:00 6 13 2 09:40
ConcVal
小於或等於 15(二進制111 1)(實際上我有 32 位,甚至將來可能更多,但為了簡化問題,它只有 4 位)。ConcVal
- 類似於Descriptions
二進制的疊加。所以ConcVal
值對於 all 可能是相同的Types
,但是第二個表中描述的含義是不同的。#2 - Descriptions ID Type CVbits Description 1 1 0 Some text for `type` 1 2 1 1 Some other text 3 1 2 Some other text 4 1 3 Some last text for type 1 5 2 0 Some text for type 2 … 8 2 3 Some last text for `type` 2
數據之間的關係由值的二進製表示構成
ConcVal
:所有為“1”的位(不包括零位)都與 #2 的列相關CVbits
,並且Type
.Type
在 #1 和 #2 中 - 同樣的事情。所以:ConcVal = 14 ( 111 0) 與 CVbits {1;2;3} 相關聯;
ConcVal = 13 ( 110 1) >> CVbits: {2;3};
ConcVal = 12 ( 110 0) >> CVbits: {2;3}。
如果談論表,下一個想像的(實際上,我做到了)連接可以幫助理解我的需求:
StateID Type ConcVal (bin) CVbits DescrID 1 1 14 (1110) 1 1 1 1 14 (1110) 2 2 1 1 14 (1110) 3 3 … 6 2 13 (1100) 2 6 … 6 2 13 (1100) 3 8
Part2(非常小)
我知道上面描述的邏輯更好地在前端實現,但我想測試可以提供多少 DBMS,所以我寫了UDF
getCVbits
,稱為left join with 子句。因此,按照您的目的,該查詢執行時間過長。300~3000 行的時間接近 1,2~2,0 秒。我猜,UDF 太慢了。但如果你願意,我想我可以給你真正的詢問。ConcVal``“,1,2,”,``“where getCVbits (a.ConcVal) LIKE concat(‘%,’b.CVbits,’,%’)”
第三部分
如果我將編寫用於
getCVbits
計算所需字元串的插入和更新觸發器怎麼辦。這個字元串我可以儲存在#1 中。這允許查詢更快,但不利於數據規範化。題:
Q1。儲存計算的 bitorderstring 是好方法還是讓使用者稍等一下?=)(我想,結果集會比我測試的要多得多)
Q2。如果使用,我如何
States
在Descriptions
沒有 LIKE 運算符的情況下加入getCVbits
?實際上,我可以從 UDF 返回任何我需要的東西。Q3。還有另一種實現表之間“關係”的方法……數據嗎?
更新: 所以,就像我承諾的那樣,2 個查詢的結果:
SELECT b.ID AS StatusID, b.Type as Type, b.CVTime AS CVTime, b.ConcVal AS ConcVal, CONV(b.ConcVal, 10, 2) AS BinStr, a.ID AS DescrID, a.CVbits AS CVbits, a.Description AS Description FROM (Reasons a JOIN States b ON ((a.Type = b.Type)))
和**#1**
WHERE (a.CVbits <> 0) AND (a.CVbits <> 8) AND (a.CVbits <> 16) AND (1 << a.CVbits) & b.ConcVal
和**#2**
就像建議的里克詹姆斯一樣:
一個更簡單(執行時更快)的解決方案是製作
CVBits
一個整數並儲存二進制等效值(1、2、4、8、16),然後使用二進制 AND 運算符ConcVal
連接。CVBits
WHERE (a.CVbits <> 0) AND (a.CVbits <> 8) AND (a.CVbits <> 16) AND (a.CV & b.ConcVal)
返回約 4280 行(持續時間/獲取)並沒有太大不同:
#1 (1<<CVbits & ConcVal) #2 (CV & ConcVal) 0.016 sec / 0.421 sec 0.015 sec / 0.687 sec 0.016 sec / 0.156 sec 0.000 sec / 0.296 sec 0.031 sec / 0.234 sec 0.016 sec / 0.171 sec 0.016 sec / 0.218 sec 0.016 sec / 0.359 sec 0.016 sec / 0.172 sec 0.016 sec / 0.125 sec
當我使用 UDF 和
LIKE
.
WHERE (1 << CVbits) & ConcVal AND CVbits != 0 -- (to "exclude the zero bit")
Q1。儲存計算的 bitorderstring 是好方法還是讓使用者稍等一下?=)(我想,結果集會比我測試的要多得多)
MySQL 支持位類型的列。正如您所期望的那樣,它們每個只使用一個位,以 8 個為一組。這將提供與您目前獲得的相同的磁碟和記憶體密度,但查詢編寫更容易。
Q2。如果使用 getCVbits,如何在沒有 LIKE 運算符的情況下將狀態加入描述?實際上,我可以從 UDF 返回任何我需要的東西。
@Rick 有它:你需要在
tblDescriptions.CVbits
. 一個更簡單(執行時更快)的解決方案是製作CVBits
一個整數並儲存二進制等效值(1、2、4、8、16),然後使用二進制 AND 運算符ConcVal
連接。CVBits
Q3。還有另一種實現表之間“關係”的方法……數據嗎?
是的。規範您的設計。
ConcVal
打破第一個範式,因為它包含許多值。創建一個僅包含tblStates.ID
和的新表tblDescriptions.ID
。請不要在表名前加上“tbl”前綴。