views:

689

answers:

5

Right now I have the following query:

SELECT name, COUNT(name), time, price, ip, SUM(price) 
  FROM tablename 
 WHERE time >= $yesterday 
   AND time <$today GROUP BY name

And what I'd like to do is add a DISTINCT by column 'ip', i.e.

SELECT DISTINCT ip FROM tablename 

So my final output would be all the columns, from all the rows that where time is today, grouped by name (with name count for each repeating name) and no duplicate ip addresses.

What should my query look like? (or alternatively, how can I add the missing filter to the output with php)?

Thanks in advance.


[UPDATE]

To minimize confusion, consider this (simplified) db table:

|   name   |   ip   |
---------------------
|  mark    |  123   |
|  mark    |  123   |
|  mark    |  456   |
|  dave    |  789   |
|  dave    |  087   |

The result I'm looking for would be an HTML table looking like this:

|  name    |  name count   |
----------------------------
|  mark    |      2        |
|  dave    |      2        |

What I'm currently getting is:

|  name    |  name count   |
----------------------------
|  mark    |      3        |
|  dave    |      2        |

(it counts mark 3 times, even though two times are with the same ip).

+1  A: 

You can just add the DISTINCT(ip), but it has to come at the start of the query. Be sure to escape PHP variables that go into the SQL string.

SELECT DISTINCT(ip), name, COUNT(name) nameCnt, 
time, price, SUM(price) priceSum
FROM tablename 
WHERE time >= $yesterday AND time <$today 
GROUP BY ip, name
Andy
Adam
It's better to alias the columns so you can refer to them by the alias in PHP rather than having to use $result['COUNT(name)'] - instead with alias $result['nameCnt']. I think you'll have to `GROUP BY ip, name`, answer updated
Andy
You can't really do that -- distinct isn't a function; it's a keyword which applies to the entire row, or a modifier on an aggregate function. In your case, it's a keyword for SELECT, which is why it has to come before the column names. The parentheses you put around 'ip' are just decorative.
Ian Clelland
+1  A: 

Somehow your requirement sounds a bit contradictory ..

group by name (which is basically a distinct on name plus readiness to aggregate) and then a distinct on IP

What do you think should happen if two people (names) worked from the same IP within the time period specified?


Did you try this?

SELECT name, COUNT(name), time, price, ip, SUM(price) 
  FROM tablename 
 WHERE time >= $yesterday AND time <$today 
GROUP BY name,ip
lexu
I tried it, didn't get the right result.The reason I want to use DISTINCT on ip, is I don't want duplicate ip's. The reason I want to use GROUP BY on name is so I can count names (e.g. show one table row that tells me how many people with the name "mark" are there).I don't (and won't) have two names on the same IP in my db.
Adam
Regarding GROUP BY name,ip ...It didn't solve the problem, I think it only groups by the first column and ignores the second.
Adam
@Adam: It groups by name and IP .. you can see this more easily by moving the IP to the second position of the select list.
lexu
@Adam: If you don't have two names with the same IP, how come the first SELECT statement in your question includes duplicate IPs? Each ID should appear with one and only one name.
Larry Lustig
@lexu not sure exactly what's going on over there, but it does not eliminate duplicates - not for names and not for ip's.
Adam
@Larry Lustig - I did not mean each ip appears with only one name. I meant that if there are two duplicate ip's, they will always have the same name. What I'm trying to do is count that name just once for that ip (i.e. removing duplicate ip's).
Adam
+3  A: 

you can use COUNT(DISTINCT ip), this will only count distinct values

knittl
yep, but it doesn't solve my problem:) thanks
Adam
Adam: Why doesn't this solve your problem?
Mark Byers
Oh hold on, wait a minute. Trying to reproduce the query to answer Marks question reveals: THIS DOES WORK!!!!! I can't believe it. I think I might cry.
Adam
+3  A: 

Replacing FROM tablename with FROM (SELECT DISTINCT * FROM tablename) should give you the result you want (ignoring duplicated rows) for example:

SELECT name, COUNT(*)
FROM (SELECT DISTINCT * FROM Table1) AS T1
GROUP BY name

Result for your test data:

dave 2
mark 2
Mark Byers
Sounds good. How do I extract the data though? (Never used SELECT within a SELECT before).Is Table1 my Table? What is T1?Thanks in advance
Adam
@Adam: Yes, `Table1` is the name of your table, while `T1` is the alias for that sub-query, so you could also write `SELECT T1.name, ...`. MySQL requires aliases for all sub-queries (+1 for this answer).
Peter Lang
Thanks Peter, and Mark.How do I use the data in my php though? I used $data = mysql_query("SELECT...") and then while($row = mysql_fetch_array($data)) { echo $row['name']; echo $row['COUNT(name)']; }But now it returns empty.
Adam
OK, update: The problem now is that if I have a Dave using the same ip as Mark once, and then another Dave that doesn't use the same ip, this query won't show me any dave's (when it should still count the Daves that aren't sharing the same ip).Tried changing DISTINCT * to DISTINCT ip, but then I get an error.
Adam
A: 

i need to use group by in my query. select (col1+col2+col3) from t1 where a=b.. group by tcol3,col4,col5. please help me out.

anil