Mysql 对于每个用户,将最近3个月的数据作为单独的列而不是行获取

Mysql 对于每个用户,将最近3个月的数据作为单独的列而不是行获取,mysql,Mysql,我有一个mysql表“bf_monthly_bill”,其中按月存储另一个表“bf_users”中每个用户的数据 我的bf_用户表的结构是 id | display_name 1 | ABC 2 | DEF 3 | GHI 4 | JKL bf\U月账单的结构为 company_id | package_price | bill_month 1 | 500 | Jan2k19 2 | 300

我有一个mysql表“bf_monthly_bill”,其中按月存储另一个表“bf_users”中每个用户的数据

我的bf_用户表的结构是

id   | display_name
1    | ABC
2    | DEF
3    | GHI
4    | JKL
bf\U月账单的结构为

company_id   | package_price  | bill_month
1            | 500            | Jan2k19
2            | 300            | Jan2k19
3            | 900            | Jan2k19
1            | 200            | Feb2k19
3            | 542            | Feb2k19
1            | 500            | Mar2k19
2            | 300            | Mar2k19
3            | 900            | Mar2k19
4            | 200            | Mar2k19
我要每个公司的名称和每个月账单上的套餐价格,例如

company_name   | first_month_bill  | second_month_bill |third_month_bill 
ABC            | 500               | 200               |   500 
DEF            | 300               | 0 or Null         |   300
GHI            | 900               | 542               |   900
JKL            | 0 or NUll         | 0 or Null         |   200
我试过的是

SELECT bf_users.display_name,first_month.package_price firstt_bill,second_month.package_price second_bill,third_month.package_price third_bill from bf_monthly_bill 
AS first_month 
JOIN bf_monthly_bill AS second_month ON first_month.company_id=second_month.company_id
JOIN bf_monthly_bill AS third_month ON first_month.company_id=third_month.company_id
JOIN bf_users ON bf_users.id=first_month.company_id
Where first_month.bill_month='Jan2k19' AND second_month.bill_month='Feb2k19' AND third_month.bill_month='Mar2k19'

这个查询的问题是,它只给我提供了那些每月都存在的公司及其各自的账单

您可以尝试使用条件聚合

select display_name,
       sum(case when bill_month='Jan2k19' then package_price end) as first_bill,
       sum(case when bill_month='Feb2k19' then package_price end) as second_bill,
       sum(case when bill_month='Mar2k19' then package_price end) as third_bill
from
(
   SELECT u.display_name,b.package_price,b.bill_month
   from bf_users u inner join bf_monthly_bill b on u.id=b.company_id
)A group by display_name

您可以尝试使用条件聚合

select display_name,
       sum(case when bill_month='Jan2k19' then package_price end) as first_bill,
       sum(case when bill_month='Feb2k19' then package_price end) as second_bill,
       sum(case when bill_month='Mar2k19' then package_price end) as third_bill
from
(
   SELECT u.display_name,b.package_price,b.bill_month
   from bf_users u inner join bf_monthly_bill b on u.id=b.company_id
)A group by display_name
  • 使用
    LEFT JOIN
    确保您获得完整的公司列表,即使任何月份都没有账单
  • 您必须手动或使用脚本创建n列
  • 您只需执行简单的联接,不需要子查询
  • 使用
    分组依据
    为每个公司生成单个记录
  • 使用
    CASE WHEN
    IF ELSE
    创建n列并仅从相关行中拾取数据。它可以是第一行或任何行,因此使用聚合函数拾取数据,即使数据位于组的任何行,也可以通过将其他行值设置为
    NULL
    作为聚合函数来排除NULL值
  • 使用
    LEFT JOIN
    确保您获得完整的公司列表,即使任何月份都没有账单
  • 您必须手动或使用脚本创建n列
  • 您只需执行简单的联接,不需要子查询
  • 使用
    分组依据
    为每个公司生成单个记录
  • 使用
    CASE WHEN
    IF ELSE
    创建n列并仅从相关行中拾取数据。它可以是第一行或任何行,因此使用聚合函数拾取数据,即使数据位于组的任何行,也可以通过将其他行值设置为
    NULL
    作为聚合函数来排除NULL值
  • 试试这个:

    SELECT bu.name, 
        max(case when (bb.bill_month='Jan2k19') then bb.package_price else NULL end) as 'first_month_bill',
        max(case when (bb.bill_month='Feb2k19') then bb.package_price else NULL end) as 'second_month_bill',
        max(case when (bb.bill_month='Mar2k19') then bb.package_price else NULL end) as 'third_month_bill'
        FROM bf_users bu
        INNER JOIN bf_monthly_bill bb
        ON bu.id = bb.bf_users_id GROUP BY bu.name;
    
    输出::

    name    first_month_bill    second_month_bill   third_month_bill
    ABC       500                   200                  500
    DEF       300                  (null)                300
    GHI       900                   542                  900
    JKL      (null)                (null)                200
    
    这里是演示

    试试这个:

    SELECT bu.name, 
        max(case when (bb.bill_month='Jan2k19') then bb.package_price else NULL end) as 'first_month_bill',
        max(case when (bb.bill_month='Feb2k19') then bb.package_price else NULL end) as 'second_month_bill',
        max(case when (bb.bill_month='Mar2k19') then bb.package_price else NULL end) as 'third_month_bill'
        FROM bf_users bu
        INNER JOIN bf_monthly_bill bb
        ON bu.id = bb.bf_users_id GROUP BY bu.name;
    
    输出::

    name    first_month_bill    second_month_bill   third_month_bill
    ABC       500                   200                  500
    DEF       300                  (null)                300
    GHI       900                   542                  900
    JKL      (null)                (null)                200
    

    以下是演示

    @BensonOO,如果您在未来数据增长时遇到此查询的性能问题。。。很少有提示将子查询排除在外,因为5.7下的MySQL倾向于具体化from子句中使用的查询。。。MySQL:5.7+倾向于在优化器中计算出自身的子查询。@BensonOO忘记提到运行
    EXPLAIN;显示警告
    在一些MySQL版本中,当重写发生时,可以显示优化器内部SQL重写。添加了:但是,当连接在旧的逗号连接中转换时,不要感到惊讶internally@BensonOO如果在将来数据增长时此查询出现性能问题。。。很少有提示将子查询排除在外,因为5.7下的MySQL倾向于具体化from子句中使用的查询。。。MySQL:5.7+倾向于在优化器中计算出自身的子查询。@BensonOO忘记提到运行
    EXPLAIN;显示警告
    在一些MySQL版本上,当重写发生时,可以显示优化器内部SQL重写。请注意:当连接在旧的逗号连接内部转换时,不要感到惊讶