私信  •  关注

spencer7593

spencer7593 最近创建的主题
spencer7593 最近回复了
6 年前
回复了 spencer7593 创建的主题 » 使用mysql生成当前30、60、90天的老化报告

指定给表达式的别名 SELECT 列表不能在 选择 列表,或 WHERE 条款。(它可供以后在语句处理中引用,在 HAVING 条款或 ORDER BY 条款)

一种方法(可能很昂贵)是使用内联视图,在其中提供别名,然后在外部查询中,可以将指定的别名作为列名引用。

SELECT v.my_alias 
  FROM ( -- inline view 
         SELECT t.foo AS my_alias 
           FROM ...
       ) v

例如

SELECT v.INV_NUM
     , v.INV_DDATE
     , v.days_past_due
     , v.total_ar
     , SUM(IF( v.days_past_due = 0               ,v.total_ar,0))
     , SUM(IF( v.days_past_due BETWEEN  1 AND 30 ,v.total_ar,0))
     , SUM(IF( v.days_past_due BETWEEN 31 AND 60 ,v.total_ar,0))
     , SUM(IF( v.days_past_due BETWEEN 61 AND 90 ,v.total_ar,0))
     , SUM(IF( v.days_past_due > 90              ,v.total_ar,0))
  FROM (
         SELECT t.INV_NUM
              , t.INV_DDATE
              , DATEDIFF(CURDATE(), FROM_UNIXTIME(t.INV_DDATE)) AS `days_past_due`
              , t.INV_DBAL                                      AS `total_ar`
           FROM invoice_table t
          WHERE t.INV_CODE = 'the_client code'
       ) v

这可能很昂贵,因为MySQL在运行外部查询之前处理内联视图、创建和填充中间表(称为“派生表”)的方式。


除此之外,我们的选择是重复同样的表达来推导“过期天数”,例如。

SELECT t.INV_NUM
     , t.INV_DDATE
     , DATEDIFF(CURDATE(),FROM_UNIXTIME(t.INV_DDATE)) AS `days_past_due`
     , t.INV_DBAL                                     AS `total_ar`
     , SUM(IF( DATEDIFF(CURDATE(),FROM_UNIXTIME(t.INV_DDATE)) = 0               ,t.INV_DBAL,0))
     , SUM(IF( DATEDIFF(CURDATE(),FROM_UNIXTIME(t.INV_DDATE)) BETWEEN  1 AND 30 ,t.INV_DBAL,0))
     , SUM(IF( DATEDIFF(CURDATE(),FROM_UNIXTIME(t.INV_DDATE)) BETWEEN 31 AND 60 ,t.INV_DBAL,0))
     , SUM(IF( DATEDIFF(CURDATE(),FROM_UNIXTIME(t.INV_DDATE)) BETWEEN 61 AND 90 ,t.INV_DBAL,0))
     , SUM(IF( DATEDIFF(CURDATE(),FROM_UNIXTIME(t.INV_DDATE)) > 90              ,t.INV_DBAL,0))
  FROM invoice_table t
 WHERE t.INV_CODE = 'the_client code'
6 年前
回复了 spencer7593 创建的主题 » mysql left join返回意外结果

我会使用条件聚合。对单个引用的联接 tall_comment_votes ,然后检查表达式中的条件。

SELECT c.id
     , SUM(IF(v.status = 1                                          ,1,0)) AS upvotes
     , SUM(IF(v.status = 1 AND v.user_id = 1 AND v.is_anonymous = 0 ,1,0)) AS userUpvoted
     , SUM(IF(v.status = 2                                          ,1,0)) AS downvotes
     , SUM(IF(v.status = 2 AND v.user_id = 1 AND v.is_anonymous = 0 ,1,0)) AS userDownvoted
  FROM talk_comments c
  LEFT
  JOIN talk_comment_votes v
    ON v.comment_id = c.id
 WHERE c.id = 2
 GROUP
    BY c.id

这避免了当v1、v2、v3和v4返回多行时部分交叉积的问题。

MySQL IF() 表达式可以替换为更符合ANSI标准的 CASE 表达式,例如

    , SUM(CASE WHEN v.status = 1 THEN 1 ELSE 0 END)  AS upvotes

追随

设置测试用例并遵守执行计划和性能

填充表

CREATE TABLE talk_comments (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT);
CREATE TABLE talk_comment_votes (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, comment_id  INT UNSIGNED NOT NULL, user_id  INT UNSIGNED NOT NULL, is_anonymous TINYINT(1) UNSIGNED NOT NULL, STATUS TINYINT UNSIGNED, time_ INT UNSIGNED); 
CREATE INDEX talk_comment_votes_IX1 ON talk_comment_votes (comment_id, STATUS, user_id, is_anonymous) ;
INSERT INTO talk_comments (id) VALUES (1),(2),(3);
INSERT INTO talk_comment_votes (id, comment_id, user_id, is_anonymous, STATUS, time_) VALUES (1,2,2,0,1,0),(2,1,1,0,1,0),(3,2,1,0,2,NULL),(4,7,1,0,2,NULL),(5,1,14,1,1,NULL),(6,2,14,1,1,NULL);

查询执行计划

EXPLAIN
SELECT c.id, COUNT(DISTINCT v1.id) AS upvotes, COUNT(DISTINCT v2.id) AS userUpvoted, COUNT(DISTINCT v3.id) AS downvotes, COUNT(DISTINCT v4.id) AS userDownvoted FROM talk_comments c
  LEFT JOIN talk_comment_votes v1 ON v1.comment_id = c.id AND v1.status = 1 
    LEFT JOIN talk_comment_votes v2 ON v2.comment_id = c.id AND v2.status = 1 AND v2.user_id = 1 AND v2.is_anonymous = 0
    LEFT JOIN talk_comment_votes v3 ON c.id = v3.comment_id AND v3.status = 2
    LEFT JOIN talk_comment_votes v4 ON c.id = v4.comment_id AND v4.status = 2 AND v4.user_id = 1 AND v4.is_anonymous = 0
WHERE c.id = 2 GROUP BY c.id
;

EXPLAIN
SELECT c.id
     , SUM(IF(v.status = 1                                          ,1,0)) AS upvotes
     , SUM(IF(v.status = 1 AND v.user_id = 1 AND v.is_anonymous = 0 ,1,0)) AS userUpvoted
     , SUM(IF(v.status = 2                                          ,1,0)) AS downvotes
     , SUM(IF(v.status = 2 AND v.user_id = 1 AND v.is_anonymous = 0 ,1,0)) AS userDownvoted
    FROM talk_comments c
    LEFT
    JOIN talk_comment_votes v
      ON v.comment_id = c.id
   WHERE c.id = 2
   GROUP BY c.id
;

explain的输出

--     id  select_type  table   type    possible_keys           key                     key_len  ref                        rows  Extra        
-- ------  -----------  ------  ------  ----------------------  ----------------------  -------  -----------------------  ------  -------------
--      1  SIMPLE       c       const   PRIMARY                 PRIMARY                 4        const                         1  Using index  
--      1  SIMPLE       v1      ref     talk_comment_votes_IX1  talk_comment_votes_IX1  6        const,const                   2  Using index  
--      1  SIMPLE       v2      ref     talk_comment_votes_IX1  talk_comment_votes_IX1  11       const,const,const,const       1  Using index  
--      1  SIMPLE       v3      ref     talk_comment_votes_IX1  talk_comment_votes_IX1  6        const,const                   1  Using index  
--      1  SIMPLE       v4      ref     talk_comment_votes_IX1  talk_comment_votes_IX1  11       const,const,const,const       1  Using index  



--     id  select_type  table   type    possible_keys           key                     key_len  ref       rows  Extra        
-- ------  -----------  ------  ------  ----------------------  ----------------------  -------  ------  ------  -------------
--      1  SIMPLE       c       const   PRIMARY                 PRIMARY                 4        const        1  Using index  
--      1  SIMPLE       v       ref     talk_comment_votes_IX1  talk_comment_votes_IX1  4        const        3  Using index  

测量性能:

100 executions                        round 1      round 2     round 3
------------------------------------  ----------   ----------  ---------
multiple left join, count(distinct    0.123 secs   0.130 secs  0.125 secs
conditional aggregation sum(if        0.113 secs   0.114 secs  0.111 secs
7 年前
回复了 spencer7593 创建的主题 » mysql按排序列值选择多个列组

我们只需要表达式对n1、n2和n3列中的值进行“排序”。如果我们有,我们可以做一个简单的 GROUP BY COUNT .

SELECT COUNT(1) AS total
     , IF(t.n1<=t.n2,IF(t.n1<=t.n3,t.n1,t.n3),IF(t.n2<=t.n3,t.n2,t.n3)) AS n1s
     , IF(t.n1<=t.n2,IF(t.n2<=t.n3,t.n2,IF(t.n1<=t.n3,t.n3,t.n1)),IF(t.n1<=t.n3,t.n1,IF(t.n2<=t.n3,t.n3,t.n2 ))) AS n2s
     , IF(t.n1<=t.n2,IF(t.n2<=t.n3,t.n3,t.n2),IF(t.n1<=t.n3,t.n3,t.n1)) AS n3s
  FROM this_table_column_structure t
 GROUP BY n1s,n2s,n3s
 ORDER BY total DESC, n1s, n2s, n3s

将返回

total   n1s   n2s   n3s
-----  ----  ----  ----
    2     1     2     3
    2     5     6     7
    1     1     5     6
    1     3     5     6
7 年前
回复了 spencer7593 创建的主题 » 如何插入另一个表mysql中的数据[关闭]

对于中的现有行 member ,假设 to from inbox sent 表包含 id 来自的值 成员 表,然后我们可以从中获取相关行的计数 收件箱 发送 ,并将计数存储到 成员 表,包含如下内容:

UPDATE `member` m 
   SET m.inbox = ( SELECT COUNT(1) FROM `inbox` i ON i.to   = m.id )
     , m.sent  = ( SELECT COUNT(1) FROM `sent`  s ON s.from = m.id )

这个例子提出了各种无根据的假设…什么是“数据量”,收件箱和发送到成员表的表之间的关系,…

如果没有示例数据和预期的最终结果,我们只是在猜测规范,而我们提出的任何SQL都只是猜测。

当没有合适的索引时,在大型集合上相关子查询的性能可能会有问题。还有其他的查询模式将获得同等的结果。