问题
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