Count and group by in same query - mysql

bid_count is returning 1 ... how do I get it to return the correct bid count? I know that it's not returning the right count because I'm grouping by user_id. Can I alter the query so it counts also.
"SELECT id, bid, item_id, user_id, MAX(bid) AS max_bid, COUNT(bid) AS bid_count, bid_date
FROM bids
WHERE item_id = ?
GROUP BY user_id ORDER BY id DESC"

You shouldn't use unaggregated expressions in GROUP BY unless they are all same within the group.
If you want to return the record holding the counts by user_id, you should use an subquery to get the counts then join them to the result:
SELECT id, bid, item_id, user_id, bid_date, max_bid, bid_count
FROM bids
LEFT JOIN
(SELECT user_id,MAX(bid) AS max_bid, COUNT(bid) AS bid_count
FROM bids
WHERE item_id = ?
GROUP BY user_id ) as group_table
ON bids.user_id = group_table.user_id
WHERE bids.item_id = ?

Try grouping it based on item_id. item_id should the one that has different bids.

Related

How to exclude specific duplicates from MySQL group_by dataset?

I'm using MySQL 5.7.12. I have a simple query that looks like the following:
SELECT COUNT(id) as count, pic_id
FROM user_pictures
GROUP BY pic_id
I would like to exclude all the duplicate USER_ID records from grouping. So I did the following, however, it's not returning any result:
SELECT COUNT(id) as count, pic_id
FROM user_pictures
GROUP BY pic_id
HAVING count(user_id) = 1
What am I missing here?
Use DISTINCT so it doesn't count duplicates of the same user_id:
SELECT COUNT(id) as count, pic_id
FROM user_pictures
GROUP BY pic_id
HAVING count(DISTINCT user_id) = 1

MySQL - Group and total, but return all rows in each group

I'm trying to write a query that finds each time the same person occurs in my table between a specific date range. It then groups this person and totals their spending for a specific range. If their spending habits are greater than X amount, then return each and every row for this person between date range specified. Not just the grouped total amount. This is what I have so far:
SELECT member_id,
SUM(amount) AS total
FROM `sold_items`
GROUP BY member_id
HAVING total > 50
This is retrieving the correct total and returning members spending over $50, but not each and every row. Just the total for each member and their grand total. I'm currently querying the whole table, I didn't add in the date ranges yet.
JOIN this subquery with the original table:
SELECT si1.*
FROM sold_items AS si1
JOIN (SELECT member_id
FROM sold_items
GROUP BY member_id
HAVING SUM(amount) > 50) AS si2
ON si1.member_id = si2.member_id
The general rule is that the subquery groups by the same column(s) that it's selecting, and then you join that with the original query using the same columns.
SELECT member_id, amount
FROM sold_items si
INNER JOIN (SELECT member_id,
SUM(amount) AS total
FROM `sold_items`
GROUP BY member_id
HAVING total > 50) spenders USING (member_id)
The query you have already built can be used as a temporary table to join with. if member_id is not an index on the table, this will become slow with scale.
The word spenders is a table alias, you can use any valid alias in its stead.
There are a few syntaxes that will get the result you are looking, here is one using an inner join to ensure that all rows returned have a member_id in the list returned by the group by and that the total is repeated for each a certain member has:
SELECT si.*, gb.total from sold_items as si, (SELECT member_id as mid,
SUM(amount) AS total
FROM `sold_items`
GROUP BY member_id
HAVING total > 50) as gb where gb.mid=si.member_id;
I think that this might help:
SELECT
member_id,
SUM(amount) AS amount_value,
'TOTAL' as amount_type
FROM
`sold_items`
GROUP BY
member_id
HAVING
SUM(amount) > 50
UNION ALL
SELECT
member_id,
amount AS amount_value,
'DETAILED' as amount_type
FROM
`sold_items`
INNER JOIN
(
SELECT
A.member_id,
SUM(amount) AS total
FROM
`sold_items` A
GROUP BY
member_id
HAVING
total <= 50
) AS A
ON `sold_items`.member_id = A.member_id
Results of the above query should be like the following:
member_id amount_value amount_type
==========================================
1 55 TOTAL
2 10 DETAILED
2 15 DETAILED
2 10 DETAILED
so the column amount_type would distinguish the two specific member groups
You could do subquery with EXISTS as an alternative:
select *
from sold_items t1
where exists (
select * from sold_items t2
where t1.member_id=t2.member_id
group by member_id
having sum(amount)>50
)
ref: http://dev.mysql.com/doc/refman/5.7/en/exists-and-not-exists-subqueries.html
In case you need to group by multiple columns, you can use a composite identifier with concatenate in combination with a group by subquery
select id, key, language, group
from translation
--query all key-language entries by composite identifier...
where concat(key, '_', language) in (
--by lookup of all key-language combinations...
select concat(key, '_', language)
from translation
group by key, language
--that occur more than once
having count(*) > 1
)

show all data only group by specific rows : Select * from table group by column having column = 'value'

I use mysql. My table look like this:
Last I try to use this query
SELECT * FROM movie GROUP BY `group` HAVING cateogry = 'TV'
I want with this query result as: show all but only GROUP BY TV category, where category = 'TV'
I want this Result
But my query give me this result (HAVING in query work as WHERE clouse)
IF I use this QUERY
SELECT * FROM movie GROUP BY `group`
It give me this result
I want -> QUERY -> GROUP BY group (ID no 9 and ID 1,2,3 treat as different group name)
IF group has all same values BUT category='movie' (RETURN ALL ROWS
group by NOT APPLY)
IF group has all same values BUT category='TV' (RETURN 1 ROW group by APPLY)
You seem to want this query:
select m.*
from movie m join
(select `group`, min(id) as minid
from movie
group by `group`
) g
on m.id = g.minid;
SELECT min(ID) as ID, min(Name), `group`, Category
FROM movie
GROUP BY `group`, Category
ORDER BY ID
Have you tried the below? I think you are pretty close. As when you are grouping your 'group' t. You are also grouping the one whose category is movie as well. So you just need to create a separate group Category.
SELECT * FROM movie
WHERE group = 't'
GROUP BY group, Category
ORDER BY ID

Obtain a list with the items found the minimum amount of times in a table

I have a MySQL table where I have a certain id as a foreign key coming from another table. This id is not unique to this table so I can have many records holding the same id.
I need to find out which ids are seen the least amount of times in this table and pull up a list containing them.
For example, if I have 5 records with id=1, 3 records with id=2 and 3 records with id=3, I want to pull up only ids 2 & 3. However, the data in the table changes quite often so I don't know what that minimum value is going to be at any given moment. The task is quite trivial if I use two queries but I'm trying to do it with just one. Here's what I have:
SELECT id
FROM table
GROUP BY id
HAVING COUNT(*) = MIN(SELECT COUNT(*) FROM table GROUP BY id)
If I substitute COUNT(*) = 3, then the results come up but using the query above gives me an error that MIN is not used properly. Any tips?
I would try with:
SELECT id
FROM table
GROUP BY id
HAVING COUNT(*) = (SELECT COUNT(*) FROM table GROUP BY id ORDER BY COUNT(*) LIMIT 1);
This gets the minimum selecting the first row from the set of counts in ascendent order.
You need a double select in the having clause:
SELECT id
FROM table
GROUP BY id
HAVING COUNT(*) = (SELECT MIN(cnt) FROM (SELECT COUNT(*) as cnt FROM table GROUP BY id) t);
The MIN() aggregate function is suposed to take a column, not a query. So, I see two ways to solve this:
To properly write the subquery, or
To use temp variables
First alternative:
select id
from yourTable
group by id
having count(id) = (
select min(c) from (
select count(*) as c from yourTable group by id
) as a
)
Second alternative:
set #minCount = (
select min(c) from (
select count(*) as c from yourTable group by id
) as a
);
select id
from yourTable
group by id
having count(*) = #minCount;
You need to GROUP BY to produce a set of grouped values and additional select to get the MIN value from that group, only then you can match it against having
SELECT * FROM table GROUP BY id
HAVING COUNT(*) =
(SELECT MIN(X.CNT) AS M FROM(SELECT COUNT(*) CNT FROM table GROUP BY id) AS X)

Count unique users from db

I have the following table structure in my db (MySQL):
id group_id item_id project_id user_id
Users can have multiple entries withing the same project. How do I count unique users withing a particular project (minus project owner id)?
SELECT COUNT(user_id) AS cnt
FROM myTable
WHERE project_id = $myProject
AND user_id != 3
GROUP BY user_id
This looks right but I don't believe I'm getting the right results. Am I missing something?
Select Count(Distinct user_id)
From MyTable
Where project_id = $myProject
And user_id != 3
Add DISTINCT to your COUNT and eliminate the GROUP BY.
SELECT COUNT(DISTINCT user_id) AS cnt
FROM myTable
WHERE project_id = $myProject
AND user_id != 3
You don't need a GROUP BY clause for this.
SELECT COUNT(DISTINCT user_id) AS cnt
FROM myTable
WHERE project_id = $myProject
AND user_id != 3;
If you want to list the member count for each group in the same query, you can GROUP BY project_id:
SELECT COUNT(DISTINCT user_id) AS cnt
FROM myTable
GROUP BY project_id;
By grouping on user_id as you do now, every row in the resultset will contain 1.
Try Distinct?
SELECT DISTINCT COUNT(user_id) AS cnt FROM myTable WHERE project_id = $myProject AND user_id != 3