Count number of distinct rows for multiple values

梦想的初衷 提交于 2019-12-04 03:53:37

问题


Let's consider this table specifing how many times a person bought a property.

+--------+----------+
|  user  | property |
+--------+----------+
| john   | car      |
| john   | car      |
| john   | house    |
| peter  | car      |
| peter  | car      |
| amanda | house    |
| amanda | house    |
+--------+----------+

I need to know how many times a car was bought once, how many times a house was bought once, etc. Something like this:

+----------+---+---+
| property | 1 | 2 |
+----------+---+---+
| cars     | 4 | 2 |
| house    | 3 | 1 |
+----------+---+---+
  • How many times a car was bought? Four, two for peter and two for john.
  • How many times a car was bought twice? Two, for the same guys.
  • How many times a house was bought? Three, two for amanda and once for john.
  • How many times a house was bought twice? Only once, for amanda

Is this possible to do this only using SQL queries?

  • I don't care about performance or hackish ways.
  • There are more than two frequencies.
  • There's a fixed set of time a person can buy a property (5) so it's not problem to specify the columns manually in the query. I mean there's not problem doing something like:

    SELECT /* ... */ AS 1, /* ... */ AS 2, /* ... */, AS 3 /* ... */
    

回答1:


SELECT DISTINCT @pr := prop,
    (SELECT COUNT(1) FROM tbl WHERE prop = @pr LIMIT 1),
    (SELECT COUNT(1) FROM 
        (SELECT *, COUNT(*) cnt
        FROM tbl
        GROUP BY usr, prop
        HAVING cnt = 2) as tmp
        WHERE `tmp`.prop = @pr LIMIT 1)
FROM tbl;

Yes, it is not the best method; but hey, you get the answers as desired.

Also, it'll generate the results for any kind of property in your table.

The fiddle link lies here.

P.S.: 60 tries O_O




回答2:


I am here since you posted the question. Good one...
Here is a way to do it exactly as you asked for, with just groups and counts.
The trick is that I concatenate the user and property columns to produce a unique "id" for each, if we could call it that. It should work independently of the count of purchases.

SELECT C.`property`, COUNT(C.`property`), D.`pcount` from `purchases` C
LEFT JOIN(
  SELECT A.`property`, B.`pcount` FROM `purchases` A
  LEFT JOIN (
    SELECT `property`,
           CONCAT(`user`, `property`) as conc,
           COUNT(CONCAT(`user`, `property`)) as pcount
    FROM `purchases` GROUP BY CONCAT(`user`, `property`)
  ) B
  ON A.`property` = B.`property`
  GROUP BY B.pcount
) D
ON C.`property` = D.`property`
GROUP BY C.`property`



回答3:


SQL Fiddle

MySQL 5.5.30 Schema Setup:

CREATE TABLE Table1
    (`user` varchar(6), `property` varchar(5))
;

INSERT INTO Table1
    (`user`, `property`)
VALUES
    ('john', 'car'),
    ('john', 'car'),
    ('john', 'house'),
    ('peter', 'car'),
    ('peter', 'car'),
    ('amanda', 'house'),
    ('amanda', 'house')
;

Query 1:

select t.property, t.total, c1.cnt as c1, c2.cnt as c2, c3.cnt as c3
from
  (select 
    t.property , 
    count(t.property) as total
  from Table1 t
  group by t.property
  ) as t
  left join (
      select property, count(*) as cnt
      from (
          select 
            property, user, count(*) as cnt
          from table1
          group by property, user
          having count(*) = 1
        ) as i1
      group by property
  ) as c1 on t.property = c1.property
  left join (
      select property, count(*) as cnt
      from (
          select 
            property, user, count(*) as cnt
          from table1
          group by property, user
          having count(*) = 2
        ) as i2
      group by property
  ) as c2 on t.property = c2.property
  left join (
      select property, count(*) as cnt
      from (
          select 
            property, user, count(*) as cnt
          from table1
          group by property, user
          having count(*) = 3
        ) as i3
      group by property
  ) as c3 on t.property = c3.property

Results:

| PROPERTY | TOTAL |     C1 | C2 |     C3 |
-------------------------------------------
|      car |     4 | (null) |  2 | (null) |
|    house |     3 |      1 |  1 | (null) |



回答4:


You may try following.

SELECT COUNT(TABLE1.PROPERTY) AS COUNT, PROPERTY.USER FROM TABLE1
INNER JOIN (SELECT DISTINCT PROPERTY, USER FROM TABLE1) AS PROPERTY
ON PROPERTY.PROPERTY = TABLE1.PROPERTY
AND PROPERTY.USER = TABLE1.USER
GROUP BY TABLE1.USER, PROPERTY.PROPERTRY

tested similar in MySQL




回答5:


try this

    SELECT property , count(property) as bought_total , count(distinct(user)) bought_per_user
    FROM Table1
    GROUP BY property

the output will be like that

  PROPERTY  |   BOUGHT_TOTAL     |  BOUGHT_PER_USER
  ________________________________________________________
    car     |            4       |       2
    house   |            3       |       2

DEMO SQL FIDDLE HERE




回答6:


You should be able to do this with sub-selects.

SELECT property, user, COUNT(*) FROM purchases GROUP BY property, user;

will return you the full set of grouped data that you want. You then need to look at the different frequencies:

SELECT property, freq, COUNT(*) FROM (SELECT property, user, COUNT(*) freq FROM purchases GROUP BY property, user) AS foo GROUP BY property, freq;

It's not quite in the format that you illustrated but it returns the data




回答7:


I hope this can help u.....let us create one table first:

create table prop(user varchar(max),property varchar(max))

insert into prop values('john','car'),insert into prop values('john','car'), insert into prop values('john','house'),insert into prop values('peter','car'),

insert into prop values('peter','car'),insert into prop values('amanda','house'), insert into prop values('amanda','house')

1)how many times car was bought?

ANS: select count(property) from prop where property = 'car' (4)

2)How many times a car was bought twice?

ANS: select user,COUNT(property) from prop where property = 'car' group by user having COUNT(property) = 2

2-john 2-peter

3)How many times a house was bought?

ANS: select COUNT(property) from prop where property = 'house' (3) 4)How many times a house was bought twice? ANS: select user,COUNT(property) from prop where property='house' group by user having COUNT(property)< =2 2-amanda 1-john



来源:https://stackoverflow.com/questions/15101941/count-number-of-distinct-rows-for-multiple-values

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!