-2

MySQL DB には、次の列を持つ purchases テーブルがあります。

USERID PURCHASE_AMOUNT  
3         20
9         30
3         5
4         5
1         10
1         5

このようなレポートを作成したいと思います

SUM_OF_PURCHASES_RANGE NUM_OF_USERS  
0-1                    0
1-5                    1
5-20                   1
20-30                  2

意味: 最大 1 (購入の合計) (購入の合計) を購入したユーザーは 0 人、1 から 5 の間で購入したユーザーは 1 人など...

生成するにはどのクエリを使用すればよいですか?

4

6 に答える 6

1

を使用して範囲を作成しUNION、それだけLEFT JOINですべてのカテゴリを取得できます。(目的の結果の変更のために編集されました)

SELECT CONCAT(base.lower,'-',base.upper) PURCHASE_RANGE, COUNT(userid) NUM_OF_USERS
FROM (
  SELECT 0 lower, 1 upper UNION SELECT 2, 5 UNION SELECT 6,20 UNION SELECT 21,30
) base
LEFT JOIN (
  SELECT userid, SUM(purchase_amount) pa FROM purchases GROUP BY userid
) p
  ON p.pa >= base.lower AND p.pa <= base.upper
GROUP BY base.upper

でテストする SQLfiddle

于 2013-07-07T21:24:18.043 に答える
1

より簡単な構文:

SELECT PURCHASE_RANGE , COUNT(*) as NUM_OF_USERS  
FROM 
(
SELECT 
CASE 
    WHEN PURCHASE_AMOUNT <= 1 THEN 1
    WHEN PURCHASE_AMOUNT > 1 AND PURCHASE_AMOUNT <= 5 THEN 5
    WHEN PURCHASE_AMOUNT > 5 AND PURCHASE_AMOUNT <= 10 THEN 10 
    WHEN PURCHASE_AMOUNT > 10 AND PURCHASE_AMOUNT <= 20 THEN 20
    WHEN PURCHASE_AMOUNT > 20 AND PURCHASE_AMOUNT <= 30 THEN 30 END AS PURCHASE_RANGE  
FROM Table1
) AS A
GROUP BY PURCHASE_RANGE
ORDER BY PURCHASE_RANGE

SqlFiddle

于 2013-07-07T20:43:14.080 に答える
0

行で必要な値を取得するには、関心のあるすべての値を含むドライバー テーブルから開始し、次にleft outer joinデータを取得する必要があります。

select driver.mina, coalesce(sum(cnt), 0) as Num_Of_Users
from (select 1 as mina, 5 as maxa union all
      select 5, 10 union all
      select 10, 20 union all
      select 20, 30 union all
      select 30, NULL
     ) driver left outer join
     (select purchase_amount, count(*) as cnt
      from purchases
      group by purchase_amount
     ) pa
     on driver.mina >= pa.purchase_amount and
        (pa.purchase_amount < driver.maxa or driver.maxa is null)
group by driver.mina
order by driver.mina

実際には、インナーなしでこれを行うことができますgroup by。結合する前に、(特にあなたの例では) データのサイズを大幅に削減する可能性があります。

各行に範囲の下限と上限の両方を含めることをお勧めします。

于 2013-07-07T20:51:37.567 に答える
0

パフォーマンスが必要な場合は、これを行うより高速な方法があります (これにより、完全なテーブル スキャンが実行されます) が、これを試してください。

SELECT 
SUM(CASE WHEN purchase_amount BETWEEN 0 AND 1 THEN 1 ELSE 0) bucket_0_to_1,
SUM(CASE WHEN purchase_amount BETWEEN 1 AND 5 THEN 1 ELSE 0) bucket_1_to_5,
SUM(CASE WHEN purchase_amount BETWEEN 5 AND 20 THEN 1 ELSE 0) bucket_5_to_20,
SUM(CASE WHEN purchase_amount BETWEEN 20 AND 30 THEN 1 ELSE 0) bucket_20_to_30,
SUM(CASE WHEN purchase_amount > 30 THEN 1 ELSE 0) bucket_over_30, FROM my_table LIMIT 1;
于 2013-07-07T20:39:01.713 に答える
0

範囲が変更される場合、これはより簡単になる可能性があります。

with ranges(rstart, rfinish) as (
    select  0,  1 union all
    select  2,  5 union all
    select  6, 20 union all
    select 21, 30
), purchases(amount) as (
    select sum(PURCHASE_AMOUNT)
    from <purchases_basetable> -- <-- your tablename goes here
    group by USERID
)
select
    -- concat(case when r.rstart = 0 then 0 else r.rstart-1 end, '-', r.rfinish) as SUM_OF_PURCHASES_RANGE /* op's name for the group */,
    concat(r.rstart, '-', r.rfinish) as SUM_OF_PURCHASES_RANGE /* better name for the group */,
    count(*) as NUM_OF_USERS
from
    purchases as p inner join
    ranges as r
        on p.amount between r.start and r.finish
group by r.rstart, r.rfinish
order by r.rstart, r.rfinish

mysql クエリ プランがどのようになるかわかりません。テーブル式ではなく派生テーブルを使用するようにクエリを変更するのは簡単です。(しかし、とにかく以下に含めます。)

UNPIVOT 操作は、それをサポートするプラットフォームで役立つ場合もあります。

select
    -- concat(case when r.rstart = 0 then 0 else r.rstart-1 end, '-', r.rfinish) as SUM_OF_PURCHASES_RANGE /* op's name for the group */,
    concat(r.rstart, '-', r.rfinish) as SUM_OF_PURCHASES_RANGE /* better name for the group */,

    count(*) as NUM_OF_USERS
from
    (
        select sum(PURCHASE_AMOUNT) as amount
        from <purchases_basetable> -- <-- your tablename goes here
        group by USERID
    ) as p inner join
    (
        select  0 as rstart, 1 as rfinish union all
        select  2,  5 union all
        select  6, 20 union all
        select 21, 30
    ) as r
        on p.amount between r.start and r.finish
group by r.rstart, r.rfinish
order by r.rstart, r.rfinish
于 2013-07-07T20:48:17.537 に答える
0

これを試して

    select PURCHASE_RANGE , NUM_OF_USERS 
 from (
 select 1 as PURCHASE_RANGE ,count(*) as  NUM_OF_USERS  from table1 where PURCHASE_AMOUNT between 0 and 1
  union all
 select 5 ,count(*) from table1 where PURCHASE_AMOUNT between 1 and 5
 union all
 select 20 ,count(*) from table1 where PURCHASE_AMOUNT between 6 and 20
  union all
 select 30 ,count(*) from table1 where PURCHASE_AMOUNT between 21 and 30
)t

デモはこちら

于 2013-07-07T20:34:55.507 に答える