从表A中选择有限的最高值,并按表B排序

时间:2017-07-21 11:13:48

标签: mysql sql

我很难写一个解决这个问题的查询。 我的表看起来像:

表A

id | u_id | open | date
---+------+------+------------
 1 |    8 |   2  | 2017-07-20 (BBB)
 2 |  101 |   1  | 2017-07-20 (MMM)
 3 | 5475 |   3  | 2017-07-20 (WWW)
 4 |  147 |   1  | 2017-07-21 (PPP)
 5 |  149 |   1  | 2017-07-21 (QQQ)
 6 |  147 |   2  | 2017-07-16 (PPP)

(u_id being foreign key to Table B)

表B

 id  | name | amm
-----+------+---
   4 | AAA  | 4
   5 | BBB  | 5
 101 | MMM  | 3
 110 | NNN  | 3
 146 | OOO  | 3
 147 | PPP  | 6
 149 | QQQ  | 3
5475 | WWW  | 2

我正在寻找的结果需要应用以下规则:

  1. 从表B中选择所有id, names 来自表A的open, date(或NULL,如果id不存在则为NULL)
  2. 每个名称只有1个结果,表A为MAX(date)
  3. 表A中open>1的{​​{1}}
  4. 从中选择表B中排名前50位的MAX(date)
  5. 按字母顺序返回按amm排序的结果
  6. 所以基本上:表B中的所有内容,在表A中排除 id,其中name表示来自该ID的LARGEST日期等于1。

    假设我们将选择限制为4,然后在规则4之后。结果将是:

    open

    最后,我希望结果按字母顺序排序:

    id   | name | open | date
    -----+------+------+-----------
       5 | BBB  |  2   | 2017-07-20 //open>1,   nr.2 highest amm,
       6 | AAA  | NULL | NULL       //not in A, nr.3 highest amm, 
     110 | NNN  | NULL | NULL       //not in A, nr.4 highest amm, 
     146 | OOO  | NULL | NULL       //not in A, nr.6 highest amm, 
    
     NOT SELECTING:
     MMM: open =1
     PPP: at LARGEST date => open =1
     WWW: outside LIMIT
    

    目前,我有这个问题:

    id   | name | open | date
    -----+------+------+-----------
       6 | AAA  | NULL | NULL       
       5 | BBB  |  2   | 2017-07-20
     110 | NNN  | NULL | NULL
     146 | OOO  | NULL | NULL
    

    这确实给了我SELECT t3.id, t3.name, t3.open, t3.amm, t3.date FROM( SELECT t1.id, t1.name, t1.amm, t2.open, MAX(t2.date) AS date FROM Table_B AS t1 LEFT JOIN Table_A AS t2 ON t1.id = t2.u_id AND (t2.open>1 OR t2.open IS NULL) GROUP BY t1.id ORDER BY t1.amm DESC, LIMIT 20 ) AS t3 ORDER BY t3.name amm排序的结果。 不执行的内容是正确过滤name组合。对于某些date/open,它只会找到最后date个,而u_id只会找到相应的MAX(date)值。

    所以结果仍然包含:

    open

    尽管还有一个

     147 | PPP  |  2  | 2017-07-16
    

    这是SQLfiddle 147 | PPP | 1 | 2017-07-19 在结果中,不应该在哪里。

1 个答案:

答案 0 :(得分:0)

我已经放弃了试图从这块石头上抽血。

据我所知,你可以告诉你以下事情;我已将这些表重命名为更易理解的内容。

最后一部分,我只是在应用程序代码中对结果数组进行排序......

DROP TABLE IF EXISTS log;

CREATE TABLE log
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,u_id INT NOT NULL
,open TINYINT NOT NULL
,date DATE NOT NULL
);

INSERT INTO log VALUES
(1,   8,2,'2017-07-20'),
(2, 101,1,'2017-07-20'),
(3,5475,3,'2017-07-20'),
(4, 147,1,'2017-07-21'),
(5, 149,1,'2017-07-21'),
(6, 147,2,'2017-07-16');

DROP TABLE IF EXISTS users;

CREATE TABLE users
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,name VARCHAR(12) NOT NULL
,amm TINYINT NOT NULL
);

INSERT INTO users VALUES
(   4,'AAA',4),
(   5,'BBB',5),
( 101,'MMM',3),
( 110,'NNN',3),
( 146,'OOO',3),
( 147,'PPP',6),
( 149,'QQQ',3),
(5475,'WWW',2);

SELECT * 
  FROM users u 
  LEFT 
  JOIN 
     ( SELECT x.*  
         FROM log x
         JOIN 
            ( SELECT u_id, MAX(date) date FROM log WHERE open > 1 GROUP BY u_id ) y
           ON y.u_id = x.u_id
          AND y.date = x.date
     ) l
    ON l.u_id = u.id
 ORDER 
    BY amm DESC LIMIT 50;

+------+------+-----+------+------+------+------------+
| id   | name | amm | id   | u_id | open | date       |
+------+------+-----+------+------+------+------------+
|  147 | PPP  |   6 |    6 |  147 |    2 | 2017-07-16 |
|    5 | BBB  |   5 | NULL | NULL | NULL | NULL       |
|    4 | AAA  |   4 | NULL | NULL | NULL | NULL       |
|  149 | QQQ  |   3 | NULL | NULL | NULL | NULL       |
|  101 | MMM  |   3 | NULL | NULL | NULL | NULL       |
|  110 | NNN  |   3 | NULL | NULL | NULL | NULL       |
|  146 | OOO  |   3 | NULL | NULL | NULL | NULL       |
| 5475 | WWW  |   2 |    3 | 5475 |    3 | 2017-07-20 |
+------+------+-----+------+------+------+------------+