[英]MySQL - creating more results than one starts with (example: integers within an interval)
我可以回到帶有while循環的程序(也許,我以前從未嘗試過這樣做)但是必須有更快的方法。
[backspaced stuff - 我只是展示描述]
CREATE TABLE `table` (
`ZoneId` int(10) unsigned NOT NULL AUTO_INCREMENT,
`VolumeId` int(10) unsigned NOT NULL,
`TypeId` int(10) unsigned NOT NULL,
`ExtraTypeInfo` int(10) unsigned NOT NULL,
`Time` int(10) unsigned NOT NULL,
`StartIndex` int(10) unsigned NOT NULL,
`EndIndex` int(10) unsigned NOT NULL,
`SectionId` int(10) unsigned NOT NULL,
PRIMARY KEY (`ZoneId`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
StartIndex
和EndIndex
表示一個范圍,它表示從開始到結束的所有內容都有此記錄描述的屬性(比如一個范圍覆蓋300,000這比300,000行更好,這些項目也不需要ID,它們的位置是它們的ID)
一些索引將被覆蓋兩次,例如范圍[1,20]
和[1,1]
, TypeId
0表示1
已表示)兩次,2-20(僅包括一次),其余為0次。
我不是閱讀表並保持手動計數,而是將工作轉移到MySQL,我(遺憾地)必須使用PHP,如果我每個條目使用一個數組或對象,它會占用太多內存,如果我使用它需要太長時間一個位域。
而不是被拋出一個查詢並使用它我寧願學習如何做到這一點,所以我希望一個解決方案有三列:
section | index | count0 | count1
其中count0是TypeId
0的區間覆蓋索引的次數, count1
是1的區間。我已經要求兩者都阻止解決方案將其作為兩個查詢來完成。 (在該字段中,這將受給定的VolumeId的限制)
部分的長度當然是已知的
假設我們使用此數據集(忽略ZoneId
, ExtraTypeInfo
和Time
以簡化):
VolId TypeId Start End Section
1 0 1 2 1
1 0 2 2 1
2 0 1 1 1
1 1 2 3 1
1 0 1 2 2
輸出(受VolId = 1)
sec ind c0 c1
1 1 1 0
1 2 2 1
1 3 1 1
1 4 0 0 <--notice this, we do know the length of sec 1 and 4 was covered by nothing
2 1 1 0
2 2 1 0
2 3 0 0
2 4 0 0
2 5 0 0
指數可以從0或1開始,很容易改變並且尚未確定(從1開始對於應用來說是最自然的,0僅對代碼有幫助)
我希望SQL可以做到這一點。 我將繼續閱讀,但我不知道該怎么做,正如我在頂部提到的,我正在考慮一個程序,該程序遍歷所有部分,調用一個程序來生成從1到長度的列表,然后搜索每個那些並希望MySQL的優化者發現正在發生的事情。
在我們的對話之后 ,我建議您創建一個包含每個可能索引值的永久number_table
:
CREATE TABLE number_table (ind SMALLINT UNSIGNED PRIMARY KEY)
SELECT bF.v|bE.v|bD.v|bC.v|bB.v|bA.v|b9.v|b8.v
|b7.v|b6.v|b5.v|b4.v|b3.v|b2.v|b1.v|b0.v ind
FROM
(SELECT 0 v UNION ALL SELECT 1<<0x0) b0,
(SELECT 0 v UNION ALL SELECT 1<<0x1) b1,
(SELECT 0 v UNION ALL SELECT 1<<0x2) b2,
(SELECT 0 v UNION ALL SELECT 1<<0x3) b3,
(SELECT 0 v UNION ALL SELECT 1<<0x4) b4,
(SELECT 0 v UNION ALL SELECT 1<<0x5) b5,
(SELECT 0 v UNION ALL SELECT 1<<0x6) b6,
(SELECT 0 v UNION ALL SELECT 1<<0x7) b7,
(SELECT 0 v UNION ALL SELECT 1<<0x8) b8,
(SELECT 0 v UNION ALL SELECT 1<<0x9) b9,
(SELECT 0 v UNION ALL SELECT 1<<0xA) bA,
(SELECT 0 v UNION ALL SELECT 1<<0xB) bB,
(SELECT 0 v UNION ALL SELECT 1<<0xC) bC,
(SELECT 0 v UNION ALL SELECT 1<<0xD) bD,
(SELECT 0 v UNION ALL SELECT 1<<0xE) bE,
(SELECT 0 v UNION ALL SELECT 1<<0xF) bF;
DELETE FROM number_table WHERE ind = 0;
然后,您可以在此表和上table
之間建立外部聯接 ,將結果限制為相關部分的最大長度:
SELECT s.SectionId,
nt.ind,
IFNULL(SUM(t.TypeID=0),0) c0,
IFNULL(SUM(t.TypeID=1),0) c1
FROM sections s
JOIN number_table nt
ON nt.ind <= s.Length
LEFT JOIN `table` t
ON t.SectionId = s.SectionId
AND nt.ind BETWEEN t.StartIndex AND t.EndIndex
AND t.VolumeId = 1
GROUP BY s.SectionId, nt.ind
在sqlfiddle上看到它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.