mysql实战练习

-- SELECT count(*) FROM fct_sales_item;
-- 
-- SELECT    * FROM    fct_sales_item
-- WHERE id<10;
-- 
-- SELECT DATE_FORMAT(dimDateID,'%Y-%m-%d') as 'date'
-- FROM dim_date
-- ORDER BY dimDateID DESC
-- LIMIT    10;
-- 
-- SELECT    now();
-- 

-- 第四章-常用函数作业
-- 1.统计 每天 购物的 顾客数,销售金额,订单量
SELECT
    DATE_FORMAT( fct_sales.dimDateID, '%Y-%m-%d' ) AS everyday,
    COUNT( DISTINCT fct_sales.dimMemberID ) AS '顾客数',
    sum( fct_sales.AMT ) AS '销售金额',
    sum( fct_sales.QTY ) AS '订单量' 
FROM
    fct_sales 
GROUP BY
    fct_sales.dimDateID -- 以天分组计算
    
ORDER BY
    fct_sales.dimDateID DESC;
    

-- 2.统计 每周 顾客数,销售金额,订单量
SELECT WEEK
    ( fct_sales.dimDateID, 1 ) AS '一年第几周',
    COUNT( fct_sales.dimMemberID ) AS '顾客数',
    sum( fct_sales.AMT ) AS '销售金额',
    sum( fct_sales.QTY ) AS '订单量' 
FROM
    dw.fct_sales 
GROUP BY
    WEEK ( fct_sales.dimDateID, 1 );  -- 以周分组计算

-- 3. 统计各个时间段的 顾客数,销售金额, 订单量
SELECT HOUR
    ( fct_sales.dimDateID ) AS '每小时hour',
    WEEKDAY( fct_sales.dimDateID ) AS '星期几',
    COUNT( fct_sales.dimMemberID ) AS '顾客数',
    sum( fct_sales.AMT ) AS '销售金额',
    sum( fct_sales.QTY ) AS '订单量' 
FROM
    dw.fct_sales 
GROUP BY
    HOUR ( fct_sales.dimDateID ),
    weekday ( fct_sales.dimDateID );


-- 4. 每天交易金额、订单数量、顾客数、平均客单价;
--    方法一: dayofyear函数 
SELECT
    DAYOFYEAR( fct_sales.dimDateID ) AS '一年第几天',
    sum( fct_sales.AMT ) AS '交易金额',
    sum( fct_sales.QTY ) AS '订单数',
    count( fct_sales.dimDateID ) AS '顾客数',
    sum( fct_sales.AMT ) / count( fct_sales.dimDateID ) AS '平均客单价' 
FROM
    fct_sales 
GROUP BY
    DAYOFYEAR( fct_sales.dimDateID );--  方法二: date_format函数
SELECT
    DATE_FORMAT( fct_sales.dimDateID, '%j' ) AS '一年第几天',
    sum( fct_sales.AMT ) AS '交易金额',
    sum( fct_sales.QTY ) AS '订单数',
    count( fct_sales.dimDateID ) AS '顾客数',
    sum( fct_sales.AMT ) / count( fct_sales.dimDateID ) AS '平均客单价' 
FROM
    fct_sales 
GROUP BY
    DATE_FORMAT( fct_sales.dimDateID, '%j' );
    
    
-- 5. 查询某周 金额最大、最小的 订单号 及对应的顾客;【自行选择】
-- 这里选择一年中23周
SELECT
    fct_sales.salesID,
    fct_sales.dimMemberID 
FROM
    fct_sales 
WHERE
    fct_sales.AMT = ( SELECT max( fct_sales.AMT ) FROM fct_sales WHERE WEEK ( fct_sales.dimDateID ) = 23 ) 
    OR fct_sales.AMT = ( SELECT min( fct_sales.AMT ) FROM fct_sales WHERE WEEK ( fct_sales.dimDateID ) = 23 );


-- 6. 统计XX日期到XX日期会员购买金额,去掉金额大于1000会员。【自行选择时间范围】
-- 统计 20170611到20170730 会员买$  去掉 $>1000
SELECT
    fct_sales.dimMemberID AS '顾客ID',
    SUM( fct_sales.AMT ) AS '购买金额' 
FROM
    fct_sales 
WHERE
    ( fct_sales.dimDateID BETWEEN 20170611 AND 20170730 ) 
GROUP BY
    fct_sales.dimMemberID 
HAVING
    sum( fct_sales.AMT ) <= 1000;

-- 7. 计算平均客单价,平均每个顾客购买金额,计算客户平均购买次数
--  客单价=销售总额(除去打折等优惠之后的算下来的钱)÷ 顾客总数
SELECT
    avg( fct_sales.AMT ) AS '客单价',
    sum( fct_sales.AMT ) / count( DISTINCT fct_sales.dimMemberID ) AS '平均每位顾客购买金额',
    COUNT( fct_sales.salesID ) / COUNT( DISTINCT fct_sales.salesID ) AS '客户平均购买次数'
FROM
    fct_sales;

-- 8. 统计订单明细表,把商品价格进3等分,统计每个区间的商品数
-- 9. 每天订单金额分布(按最大,最小分成3个等分区间)
SELECT
    ( max( AMT ) - min( AMT ) ) / 3 AS cut_amt,
    min( AMT ) AS min_amt,
    max( AMT ) AS max_amt 
FROM
    fct_sales;
SELECT
    (
    CASE
            
            WHEN fct_sales.AMT <= ( 0.17000 + 8781.943333333 ) THEN
            '[min_amt,cut_amt]' 
            WHEN fct_sales.AMT <= ( 0.17000 + 8781.943333333 * 2 ) AND ( AMT > ( 0.17000 + 8781.943333333 )) THEN
                '(min_amt+cut_amt,min_amt+cut_amt*2]' 
            WHEN fct_sales.AMT <= 26346.00000 THEN
                '(min_amt+cut_amt*2,min_amt + cut_amt*3]' 
            END 
    ) AS qj,
    count( amt ) 
    FROM
        fct_sales

GROUP BY
    (
    CASE
            
            WHEN fct_sales.AMT <= ( 0.17000 + 8781.943333333 ) THEN
            '[min_amt,cut_amt]' 
            WHEN fct_sales.AMT <= ( 0.17000 + 8781.943333333 * 2 ) AND ( AMT > ( 0.17000 + 8781.943333333 )) THEN
                '(min_amt+cut_amt,min_amt+cut_amt*2]' 
            WHEN fct_sales.AMT <= 26346.00000 THEN
                '(min_amt+cut_amt*2,min_amt + cut_amt*3]' 
            END 
    );
-- 第五章 子查询,实战练习题
-- 1. 计算2017年7月份2号每个会员购买金额, 以及每个会员购买金额占总金额的比
-- 思路:
--     先对会员进行分组, 再根据会员组,也就是每位会员购买金额进行sum, 限制条件:日期
--     通过子查询,统计在条件日期内, 全体会员购买总金额,相除计算比率
--     比率格式: 利用concat 和 round 函数 进行数据格式处理
SELECT dw.fct_sales.dimMemberID,
             sum(dw.fct_sales.AMT) AS member_money,
             (SELECT sum(AMT) from dw.fct_sales WHERE dw.fct_sales.dimDateID = 
             '20170702' AND    dw.fct_sales.dimMemberID <>0) AS total_money,
             concat(round((sum(dw.fct_sales.AMT)/(SELECT sum(AMT) from dw.fct_sales WHERE dw.fct_sales.dimDateID = 
             '20170702' AND    dw.fct_sales.dimMemberID <>0))*100,4),'%') AS member_total_rave_2
FROM fct_sales
WHERE dw.fct_sales.dimDateID = '20170702' AND    dw.fct_sales.dimMemberID <>0
GROUP by dw.fct_sales.dimMemberID
ORDER BY SUM(AMT) DESC;

-- 2. 2017年07月2号 对每位会员累计购买金额进行分段
--  思路: 
--      先进行会员分组,限制条件: 日期
--      对每一位会员sum购买金额
--      把上面查询的 作为表即子查询,生成temp临时表,用来from(除了它,其他都只能是一个字段)
--      注意: 用临时表时需用临时表别名alis, 相当于数据库中有一个临时表temp
--      再进行分段使用 case 再排序order by
SELECT  dw.temp.dimMemberID,
              member_money,
                CASE  
                            WHEN member_money < 100 THEN 'D'
                            WHEN member_money < 500 AND member_money >= 100 THEN 'C'
                            WHEN member_money < 1000 AND member_money >= 500 THEN 'B'
                            WHEN member_money >= 1000 THEN 'A'
                END AS type_money
from 
        (    SELECT dw.fct_sales.dimMemberID,
                            sum(dw.fct_sales.amt) as member_money
            FROM fct_sales
            where dw.fct_sales.dimDateID='20170702' AND dimMemberID <>0
            GROUP BY dw.fct_sales.dimMemberID
        ) AS temp
ORDER BY type_money;


-- 3. 2017年07月2号 统计累计购买金额在100到200的会员,寻找这批会员的消费记录
--  思路:
--     把累计金额100到200的会员作为筛选表 在这批会员中寻找消费记录
--     先筛选 : 时间条件 再在会员分组中筛选 金额范围
--     还需在外查询中 设置: 时间条件, 因为in后面只是会员ID ,会员也可能在 其他时间段有记录
--      IN 后面必须只有一个字段

--         SELECT dw.fct_sales.dimMemberID
--         FROM    fct_sales
--         WHERE dw.fct_sales.dimDateID = '20170702'
--         GROUP BY    dw.fct_sales.dimMemberID
--         HAVING    SUM(dw.fct_sales.AMT) >= 100 AND SUM(dw.fct_sales.AMT) <= 200 AND dw.fct_sales.dimMemberID <> 0

SELECT *
FROM dw.fct_sales
WHERE dw.fct_sales.dimDateID = '20170702' AND dw.fct_sales.dimMemberID<>0 AND dw.fct_sales.dimMemberID IN
(        SELECT dw.fct_sales.dimMemberID
        FROM    fct_sales
        WHERE dw.fct_sales.dimDateID = '20170702'
        GROUP BY    dw.fct_sales.dimMemberID
        HAVING    SUM(dw.fct_sales.AMT) >= 100 AND SUM(dw.fct_sales.AMT) <= 200 AND dw.fct_sales.dimMemberID <> 0
)
ORDER BY dw.fct_sales.AMT DESC;

-- #1 计算 7 月份某周每个会员订单数,以及每个会员订单占整体比
-- 思路:
--   用分组对会员进行分组, 统计每个会员订单数, 在通过子查询统计会员总订单数
--   挑选条件:  日期, 某周
SELECT     dw.fct_sales.dimMemberID,
                COUNT(salesNo) AS sales_num,
                CONCAT((count(salesNo)/(SELECT COUNT(salesNo) FROM dw.fct_sales WHERE (dw.fct_sales.dimDateID BETWEEN '20170703' AND '20170709') AND dimMemberID <>0 ))*100,'%') AS rate
FROM    dw.fct_sales
WHERE (dw.fct_sales.dimDateID BETWEEN '20170703' AND '20170709') AND dimMemberID <>0
GROUP BY dw.fct_sales.dimMemberID
ORDER BY rate DESC;

-- #2 对 7 月份某周每位会员累计购买金额进行分段统计,并统计每段的会员数
-- 思路:
--    子查询: 安照购买金额统计,以会员为分组  筛选条件: 时间
--     将子查询作为 临时表,再统计每段会员数
-- SELECT    dw.fct_sales.dimMemberID,
--                 sum(AMT)
-- FROM dw.fct_sales
-- WHERE  (dw.fct_sales.dimDateID BETWEEN '20170703' AND '20170709') AND dimMemberID <>0
-- GROUP BY dimMemberID
-- 
SELECT 
        (CASE 
            WHEN temp.sum_amt <= 300 THEN  '0-300'
            WHEN temp.sum_amt <= 800 AND temp.sum_amt >300 THEN '300-800'
            WHEN temp.sum_amt >800 THEN '800-'
        END    ) AS cut_type,
        COUNT(DISTINCT dimMemberID) AS memberID_number 
FROM    
    (SELECT    dw.fct_sales.dimMemberID,
                    sum(AMT) as sum_amt
    FROM dw.fct_sales
    WHERE  (dw.fct_sales.dimDateID BETWEEN '20170703' AND '20170709') AND dimMemberID <>0
    GROUP BY dimMemberID
    ) as temp 
GROUP BY CASE 
            WHEN temp.sum_amt <= 300 THEN  '0-300'
            WHEN temp.sum_amt <= 800 AND temp.sum_amt >300 THEN '300-800'
            WHEN temp.sum_amt >800 THEN '800-'
        END    ;

-- #3 查找 7 月份某周订单金额最大的会员,这个会员的所有消费记录
-- 思路:
--         

select *
from dw.fct_sales
where dimMemberID in
(        select distinct dimMemberID
        from dw.fct_sales
        where AMT in
                            (select max(AMT)
                            from dw.fct_sales
                            where dimDateID between '20170703' and '20170709'
                            and dimMemberID<>0
                            )
) 
-- AND    (dimDateID between '20170703' and '20170709' and dimMemberID<>0);
-- 月报:统计 201707 月内每天及本月累计销售金额、订单量、会员数、订单占比、会员渗透率
/* 思路:
select  天, 销售金额, 订单量, 会员数, 天订单/总订单(子查询), 天会员数(去重)/月总会员数(去重
FROM    交易事实表
WHERE   月 
GROUP BY 天
HAVING    无
ORDER BY 天     -- 只能在最后使用!!!!
UNION 
SELECT    月, ...., '100%', ''100%'
FROM    交易表
WHERE     月
GROUP BY 月
HAVING 无
ORDER BY 月
*/
-- 疑问 : SELECT count(DISTINCT dimMemberID) FROM    fct_sales  WHERE dimMemberID<>0

SELECT    dw.fct_sales.dimDateID ,
                sum(dw.fct_sales.AMT)    AS    sales_money ,
                COUNT(dw.fct_sales.salesID) AS    sales_number,
                COUNT(DISTINCT dw.fct_sales.dimMemberID) AS member_number ,
                count(dw.fct_sales.salesID)/(SELECT count(dw.fct_sales.salesID) FROM    dw.fct_sales WHERE    dw.fct_sales.dimDateID BETWEEN '20170701' AND '20170731' ) AS order_rate,
                COUNT(DISTINCT dw.fct_sales.dimMemberID)/(SELECT count(dw.fct_sales.dimMemberID) FROM    dw.fct_sales WHERE    dw.fct_sales.dimDateID BETWEEN '20170701' AND '20170731' AND dw.fct_sales.dimMemberID <> 0) AS member_rate
FROM    dw.fct_sales
WHERE    dw.fct_sales.dimDateID BETWEEN '20170701' AND '20170731'
GROUP BY    dimDateID
UNION    
SELECT    MONTH(dimDateID),
                sum(dw.fct_sales.AMT)    AS    sales_money ,
                COUNT(dw.fct_sales.salesID) AS    sales_number,
                COUNT(DISTINCT dw.fct_sales.dimMemberID) AS member_number ,
                count(dw.fct_sales.salesID)/(SELECT count(dw.fct_sales.salesID) FROM    dw.fct_sales WHERE    dw.fct_sales.dimDateID BETWEEN '20170701' AND '20170731' ) AS order_rate,
                COUNT(DISTINCT dw.fct_sales.dimMemberID)/(SELECT count(dw.fct_sales.dimMemberID) FROM    dw.fct_sales WHERE    dw.fct_sales.dimDateID BETWEEN '20170701' AND '20170731' AND dw.fct_sales.dimMemberID <> 0 ) AS member_rate
FROM    dw.fct_sales
WHERE    dw.fct_sales.dimDateID BETWEEN '20170701' AND '20170731'
GROUP BY    MONTH(dimDateID) 
ORDER BY     dimDateID;     -- 只能在最后使用!!!!

-- - 对星期进行排序 
select date_format(dimDateID,'%W') as week_day
      ,sum(AMT) as sales_money
      ,count(distinct salesID) as order_number
      ,count(distinct dimMemberID) as member_number
      ,count(distinct salesID)/(select count(distinct salesID) from dw.fct_sales
                                where dimDateID between '20170703' and '20170710') as order_rate
from dw.fct_sales
where dimDateID between '20170703' and '20170709'
group by date_format(dimDateID,'%W')
-- order by date_format(dimDateID,'%W')
union 
select date_format(dimDateID,'%W') as week_day
      ,sum(AMT) as sales_money
      ,count(distinct salesID) as order_number
      ,count(distinct dimMemberID) as member_number
      ,count(distinct salesID)/(select count(distinct salesID) from dw.fct_sales
                                where dimDateID between '20170703' and '20170710') as order_rate
from dw.fct_sales
where dimDateID between '20170703' and '20170709'
group by date_format(dimDateID,'%W');


-- - 要排序 , 用别名排序

select temp.*
from (
select date_format(dimDateID,'%W') as week_day
      ,sum(AMT) as sales_money
      ,count(distinct salesID) as order_number
      ,count(distinct dimMemberID) as member_number
      ,count(distinct salesID)/(select count(distinct salesID) from dw.fct_sales
                                where dimDateID between '20170703' and '20170710') as order_rate
from dw.fct_sales
where dimDateID between '20170703' and '20170709'
group by date_format(dimDateID,'%W')
-- order by date_format(dimDateID,'%W')
union 
select date_format(dimDateID,'%W') as week_day
      ,sum(AMT) as sales_money
      ,count(distinct salesID) as order_number
      ,count(distinct dimMemberID) as member_number
      ,count(distinct salesID)/(select count(distinct salesID) from dw.fct_sales
                                where dimDateID between '20170703' and '20170710') as order_rate
from dw.fct_sales
where dimDateID between '20170703' and '20170709'
group by date_format(dimDateID,'%W')) temp
order by week_day

猜你喜欢

转载自www.cnblogs.com/liuyuanq/p/11256165.html