Mysql
 sql >> डेटाबेस >  >> RDS >> Mysql

MySQL में संचयी योग प्राप्त करने के लिए इष्टतम क्वेरी

आप एक वेरिएबल का उपयोग कर सकते हैं - यह किसी भी जॉइन से कहीं ज्यादा तेज है:

SELECT
    id,
    size,
    @total := @total + size AS cumulativeSize,
FROM table, (SELECT @total:=0) AS t;

डेबियन 5.0 पर चलने वाले 128MB RAM के साथ पेंटियम III पर एक त्वरित परीक्षण केस यहां दिया गया है:

तालिका बनाएं:

DROP TABLE IF EXISTS `table1`;

CREATE TABLE `table1` (
    `id` int(11) NOT NULL auto_increment,
    `size` int(11) NOT NULL,
    PRIMARY KEY  (`id`)
) ENGINE=InnoDB;

20,000 यादृच्छिक संख्याएं भरें:

DELIMITER //
DROP PROCEDURE IF EXISTS autofill//
CREATE PROCEDURE autofill()
BEGIN
    DECLARE i INT DEFAULT 0;
    WHILE i < 20000 DO
        INSERT INTO table1 (size) VALUES (FLOOR((RAND() * 1000)));
        SET i = i + 1;
    END WHILE;
END;
//
DELIMITER ;

CALL autofill();

पंक्तियों की संख्या जांचें:

SELECT COUNT(*) FROM table1;

+----------+
| COUNT(*) |
+----------+
|    20000 |
+----------+

संचयी कुल क्वेरी चलाएँ:

SELECT
    id,
    size,
    @total := @total + size AS cumulativeSize
FROM table1, (SELECT @total:=0) AS t;

+-------+------+----------------+
|    id | size | cumulativeSize |
+-------+------+----------------+
|     1 |  226 |            226 |
|     2 |  869 |           1095 |
|     3 |  668 |           1763 |
|     4 |  733 |           2496 |
...
| 19997 |  966 |       10004741 |
| 19998 |  522 |       10005263 |
| 19999 |  713 |       10005976 |
| 20000 |    0 |       10005976 |
+-------+------+----------------+
20000 rows in set (0.07 sec)

अपडेट करें

मैं मूल प्रश्न में groupId द्वारा समूहीकरण से चूक गया था, और इसने निश्चित रूप से चीजों को थोड़ा पेचीदा बना दिया। मैंने तब एक समाधान लिखा था जिसमें एक अस्थायी तालिका का उपयोग किया गया था, लेकिन मुझे यह पसंद नहीं आया - यह गन्दा और अत्यधिक जटिल था। मैं चला गया और कुछ और शोध किया, और कुछ अधिक सरल और तेज लेकर आया हूं।

मैं इसके लिए सभी क्रेडिट का दावा नहीं कर सकता-वास्तव में, मैं मुश्किल से किसी का दावा कर सकता हूं, क्योंकि यह पंक्ति संख्या का अनुकरण करें सामान्य MySQL क्वेरीज़ से ।

यह बहुत ही सरल, सुंदर और बहुत तेज़ है:

SELECT fileInfoId, groupId, name, size, cumulativeSize
FROM (
    SELECT
        fileInfoId,
        groupId,
        name,
        size,
        @cs := IF(@prev_groupId = groupId, @cs+size, size) AS cumulativeSize,
        @prev_groupId := groupId AS prev_groupId
    FROM fileInfo, (SELECT @prev_groupId:=0, @cs:=0) AS vars
    ORDER BY groupId
) AS tmp;

आप बाहरी SELECT ... AS tmp को हटा सकते हैं अगर आपको prev_groupID से ऐतराज नहीं है कॉलम वापस किया जा रहा है। मैंने पाया कि यह इसके बिना थोड़ा तेज चलता है।

यहाँ एक साधारण परीक्षण मामला है:

INSERT INTO `fileInfo` VALUES
( 1, 3, 'name0', '10'),
( 5, 3, 'name1', '10'),
( 7, 3, 'name2', '10'),
( 8, 1, 'name3', '10'),
( 9, 1, 'name4', '10'),
(10, 2, 'name5', '10'),
(12, 4, 'name6', '10'),
(20, 4, 'name7', '10'),
(21, 4, 'name8', '10'),
(25, 5, 'name9', '10');

SELECT fileInfoId, groupId, name, size, cumulativeSize
FROM (
    SELECT
        fileInfoId,
        groupId,
        name,
        size,
        @cs := IF(@prev_groupId = groupId, @cs+size, size) AS cumulativeSize,
        @prev_groupId := groupId AS prev_groupId
    FROM fileInfo, (SELECT @prev_groupId := 0, @cs := 0) AS vars
    ORDER BY groupId
) AS tmp;

+------------+---------+-------+------+----------------+
| fileInfoId | groupId | name  | size | cumulativeSize |
+------------+---------+-------+------+----------------+
|          8 |       1 | name3 |   10 |             10 |
|          9 |       1 | name4 |   10 |             20 |
|         10 |       2 | name5 |   10 |             10 |
|          1 |       3 | name0 |   10 |             10 |
|          5 |       3 | name1 |   10 |             20 |
|          7 |       3 | name2 |   10 |             30 |
|         12 |       4 | name6 |   10 |             10 |
|         20 |       4 | name7 |   10 |             20 |
|         21 |       4 | name8 |   10 |             30 |
|         25 |       5 | name9 |   10 |             10 |
+------------+---------+-------+------+----------------+

20,000 पंक्ति तालिका से पिछली कुछ पंक्तियों का एक नमूना यहां दिया गया है:

|      19481 |     248 | 8CSLJX22RCO | 1037469 |       51270389 |
|      19486 |     248 | 1IYGJ1UVCQE |  937150 |       52207539 |
|      19817 |     248 | 3FBU3EUSE1G |  616614 |       52824153 |
|      19871 |     248 | 4N19QB7PYT  |  153031 |       52977184 |
|        132 |     249 | 3NP9UGMTRTD |  828073 |         828073 |
|        275 |     249 | 86RJM39K72K |  860323 |        1688396 |
|        802 |     249 | 16Z9XADLBFI |  623030 |        2311426 |
...
|      19661 |     249 | ADZXKQUI0O3 |  837213 |       39856277 |
|      19870 |     249 | 9AVRTI3QK6I |  331342 |       40187619 |
|      19972 |     249 | 1MTAEE3LLEM | 1027714 |       41215333 |
+------------+---------+-------------+---------+----------------+
20000 rows in set (0.31 sec)


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. विभिन्न डेटाबेस में विदेशी कुंजी बाधा कैसे बनाए रखें?

  2. वाक्पटु समूह Laravel 5.3 में मान्य SQL क्वेरी के साथ SQLSTATE[42000] बनायें

  3. MySQL में रेगेक्स पैटर्न को कैसे बदलें

  4. अंकगणित अतिप्रवाह त्रुटि के साथ एक तालिका बनाना

  5. MySQL चयन * से सभी पंक्तियों को वापस नहीं करता है