簡體   English   中英

MySQL - 創建比一個更開始的結果(例如:一個區間內的整數)

[英]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;

StartIndexEndIndex表示一個范圍,它表示從開始到結束的所有內容都有此記錄描述的屬性(比如一個范圍覆蓋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的限制)

部分的長度當然是已知的

假設我們使用此數據集(忽略ZoneIdExtraTypeInfoTime以簡化):

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM