Mysql优化和爆炸

时间:2015-12-03 13:35:22

标签: mysql

我有以下查询显示整个数字中前10个最多的数字对 table

select 
    p, count(p) as frequency
from
    (SELECT 
         id, 
         CASE power1 <= power2 WHEN TRUE THEN CONCAT(power1,"-",power2) ELSE CONCAT(power2,"-",power1) 
         END p 
     FROM power 
     UNION
     SELECT 
         id, 
         CASE power1<=power3 WHEN TRUE THEN CONCAT(power1,"-",power3) ELSE CONCAT(power3,"-",power1) END p 
     FROM power 
     UNION
     SELECT 
         id, 
         CASE power1<=power4 WHEN TRUE THEN CONCAT(power1,"-",power4) ELSE CONCAT(power4,"-",power1) END p 
     FROM power 
     UNION
     ...............................................
     SELECT 
         id, 
         CASE power19<=power20 WHEN TRUE THEN CONCAT(power19,"-",power20) ELSE CONCAT(power20,"-",power19) 
         END p 
     FROM power) as b
group by 
    p
order by 
    frequency desc, p asc
limit
    0, 10
  1. 如何通过ID按降序排列前100行?查询将是这样的:

    ORDER BY id LIMIT 0,100

    但我无法适应上述情况。

  2. 代码是否可以进行优化?

  3. power1,Power2是来自表格的值....如果我有一个像3,4,5,6这样的字符串然后爆炸“,”并且在此之后power1变为3,那么它会工作吗4等?

  4. 我的意思是表格格式如下:

    table2

    LATER EDIT:

    我有这样的表:

    表:data

    +----+----+-----+
    | id | nr | set | 
    +----+----+-----+
    |  1 | 52 |   1 | 
    |  2 | 47 |   1 | 
    |  3 |  4 |   1 | 
    |  4 |  3 |   1 | 
    |  5 | 77 |   1 | 
    |  6 | 71 |   1 | 
    |  7 |  6 |   1 | 
    |  8 | 41 |   1 | 
    |  9 | 15 |   1 | 
    | 10 | 79 |   1 | 
    | 11 | 35 |   2 | 
    | 12 | 50 |   2 | 
    | 13 | 16 |   2 | 
    | 14 |  1 |   2 | 
    | 15 | 32 |   2 | 
    | 16 | 77 |   2 | 
    | 17 | 30 |   2 | 
    | 18 |  7 |   2 | 
    | 19 | 20 |   2 | 
    | 20 | 28 |   2 | 
    | .. | .. | ... | 
    +----+----+-----+
    

    我喜欢34360 id

    以下查询:

    SELECT 
        `n1`.`nr` AS `num_1`,
        `n2`.`nr` AS `num_2`,
        COUNT(1) AS `total`
    
    FROM (select * from data ORDER BY id DESC limit 0,1000) AS `n1`
    
    JOIN `data` AS `n2` 
        ON `n1`.`set` = `n2`.`set` AND `n1`.`nr` < `n2`.`nr`
    
    GROUP BY `n1`.`nr`, `n2`.`nr`
    ORDER BY `total` DESC
    LIMIT 20
    

    工作正常!

    我想知道如何找出最长时间没有画在一起的数字对。每个例子:

    • 1,42(一起,作为一对)未抽取24次
    • 32,45-作为一对 - 并没有抽出22次抽奖

2 个答案:

答案 0 :(得分:2)

请考虑以下事项:

未归一化:

 id power value
  1     1     4    
  1     2     9    
  1     3    10    
  1     4    16
  2     1     6     
  2     2    12    
  2     3    15
  2     4    19
  3     1     2     
  3     2     4     
  3     3     6     
  3     4     7
  4     1     3     
  4     2     8     
  4     3    15    
  4     4    17
  5     1     2     
  5     2    10    
  5     3    11    
  5     4    14
  6     1     4     
  6     2    10    
  6     3    12    
  6     4    19
  7     1     1     
  7     2     4     
  7     3     9     
  7     4    11

归一化:

DROP TABLE IF EXISTS my_table;

CREATE TABLE my_table
(id INT NOT NULL
,power INT NOT NULL
,value INT NOT NULL
,PRIMARY KEY(id,power)
);

INSERT INTO my_table VALUES
(1,1,4),(1,2,9),(1,3,10),(1,4,16),
(2,1,6),(2,2,12),(2,3,15),(2,4,19),
(3,1,2),(3,2,4),(3,3,6),(3,4,7),
(4,1,3),(4,2,8),(4,3,15),(4,4,17),
(5,1,2),(5,2,10),(5,3,11),(5,4,14),
(6,1,4),(6,2,10),(6,3,12),(6,4,19),
(7,1,1),(7,2,4),(7,3,9),(7,4,11);

SELECT LEAST(x.value,y.value)a -- LEAST/GREATEST is only necessary in the event that 
     , GREATEST(x.value,y.value) b -- power1 value may be greater than powerN value
     , COUNT(*) freq 
  FROM my_table x 
  JOIN my_table y 
    ON y.id = x.id 
   AND y.power < x.power 
 GROUP 
    BY LEAST(x.value, y.value) -- again only necessary if using LEAST/GREATEST above
     , GREATEST(x.value,y.value) 
 ORDER 
    BY freq DESC
     , a
     , b;
+----+----+------+
| a  | b  | freq |
+----+----+------+
|  4 |  9 |    2 |
|  4 | 10 |    2 |
| 12 | 19 |    2 |
|  1 |  4 |    1 |
|  1 |  9 |    1 |
|  1 | 11 |    1 |
|  2 |  4 |    1 |
|  2 |  6 |    1 |
|  2 |  7 |    1 |
|  2 | 10 |    1 |
|  2 | 11 |    1 |
|  2 | 14 |    1 |
|  3 |  8 |    1 |
|  3 | 15 |    1 |
|  3 | 17 |    1 |
|  4 |  6 |    1 |
|  4 |  7 |    1 |
|  4 | 11 |    1 |
|  4 | 12 |    1 |
|  4 | 16 |    1 |
|  4 | 19 |    1 |
|  6 |  7 |    1 |
|  6 | 12 |    1 |
|  6 | 15 |    1 |
|  6 | 19 |    1 |
|  8 | 15 |    1 |
|  8 | 17 |    1 |
|  9 | 10 |    1 |
|  9 | 11 |    1 |
|  9 | 16 |    1 |
| 10 | 11 |    1 |
| 10 | 12 |    1 |
| 10 | 14 |    1 |
| 10 | 16 |    1 |
| 10 | 19 |    1 |
| 11 | 14 |    1 |
| 12 | 15 |    1 |
| 15 | 17 |    1 |
| 15 | 19 |    1 |
+----+----+------+

因此...

noreturn

答案 1 :(得分:0)

虽然我完全同意@Strawberry关于规范化数据的问题,但以下是如何使用当前数据结构(未经测试)的示例。

SELECT CASE a.power_val <= b.power_val WHEN TRUE THEN CONCAT(a.power_val,"-",b.power_val) ELSE CONCAT(b.power_val,"-",a.power_val) END p, 
        COUNT(a.id) as frequency
FROM
(
    SELECT id,1 AS power_col, power1 AS power_val FROM power UNION
    SELECT id,2, power2 FROM power UNION
    SELECT id,3, power3 FROM power UNION
    SELECT id,4, power4 FROM power UNION
    SELECT id,5, power5 FROM power UNION
    SELECT id,6, power6 FROM power UNION
    SELECT id,7, power7 FROM power UNION
    SELECT id,8, power8 FROM power UNION
    SELECT id,9, power9 FROM power UNION
    SELECT id,10, power10 FROM power UNION
    SELECT id,11, power11 FROM power UNION
    SELECT id,12, power12 FROM power UNION
    SELECT id,13, power13 FROM power UNION
    SELECT id,14, power14 FROM power UNION
    SELECT id,15, power15 FROM power UNION
    SELECT id,16, power16 FROM power UNION
    SELECT id,17, power17 FROM power UNION
    SELECT id,18, power18 FROM power UNION
    SELECT id,19, power19 FROM power UNION
    SELECT id,20, power20 FROM power 
    ORDER BY id DESC
    LIMIT 2000
) a
INNER JOIN 
(
    SELECT id, 1 AS power_col, power1 AS power_val FROM power UNION
    SELECT id, 2, power2 FROM power UNION
    SELECT id,3, power3 FROM power UNION
    SELECT id,4, power4 FROM power UNION
    SELECT id,5, power5 FROM power UNION
    SELECT id,6, power6 FROM power UNION
    SELECT id,7, power7 FROM power UNION
    SELECT id,8, power8 FROM power UNION
    SELECT id,9, power9 FROM power UNION
    SELECT id,10, power10 FROM power UNION
    SELECT id,11, power11 FROM power UNION
    SELECT id,12, power12 FROM power UNION
    SELECT id,13, power13 FROM power UNION
    SELECT id,14, power14 FROM power UNION
    SELECT id,15, power15 FROM power UNION
    SELECT id,16, power16 FROM power UNION
    SELECT id,17, power17 FROM power UNION
    SELECT id,18, power18 FROM power UNION
    SELECT id,19, power19 FROM power UNION
    SELECT id,20, power20 FROM power 
    ORDER BY id DESC
    LIMIT 2000
) b
ON a.id = b.id
AND a.power_col != b.power_col
GROUP BY p
ORDER BY frequency DESC, p ASC
LIMIT 0,10

注意使用标准化数据结构可能会快得多。

修改

认为以下内容可能会为您提供所需的信息。

大的子查询是获得所有可能的组合(想法是也应对从未使用过的对),第一个数字小于第二个只是为了一致性。然后将其与数据表连接以获得匹配的数字和相应的id字段。然后使用MIN获得最小的id: -

SELECT all_combo.num_1, 
        all_combo.num_2, 
        MIN(d1.id)
FROM
(
    SELECT     sub0.nr AS num_1,
                sub1.nr AS num_2
    FROM
    (
        SELECT DISTINCT nr
        FROM data
    ) sub0
    INNER JOIN
    (
        SELECT DISTINCT nr
        FROM data
    ) sub1
    WHERE sub0.nr < sub1.nr
) all_combo
LEFT OUTER JOIN data d1 ON all_combo.num_1
LEFT OUTER JOIN data d2 ON all_combo.num_2 AND d1.set = d2.set
GROUP BY all_combo.num_1, 
        all_combo.num_2