SQL COUNT on GROUP BY - mysql

This is the code i got so far
SELECT users_ID,Problem_ID
FROM 'submission'
WHERE Status = "AC"
GROUP BY users_ID,Problem_ID
I am getting these results
+----------+------------+
| Users_ID | Problem_ID |
+----------+------------+
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 1 |
| 2 | 3 |
+----------+------------+
I only want to get
+----------+------------+
| Users_ID | Problem_ID |
+----------+------------+
| 1 | 3 | -- so because there are 3 results for user_ID 1
| 2 | 2 | -- and there are 2 results for user_ID 2
+----------+------------+
So the Problem_ID is how many rows I am getting from my query for each user.
But how do I accomplish this?
Edit:
I forgot mention that the table contains duplicates of the same problem for example.
I got a Problem with the ID of 1 and then in the database there could be two rows with the same user and with status as "AC" but I want to only get one of them.

SELECT users_ID, count(Problem_ID) as `problem_count`
FROM `submission`
WHERE Status = 'AC'
GROUP BY users_ID;

This should work:
SELECT users_ID, COUNT(DISTINCT Problem_ID)
FROM `submission`
WHERE Status = 'AC'
GROUP BY users_ID

You can do something like this :
SELECT
s.users_ID
,count(s.Problem_ID)+CASE WHEN IFNULL(userDupli.nbrUserAC, 0) > 0 THEN 1 ELSE 0 END as `problem_count`
FROM
`submission` s
left join (SELECT
users_ID
,count(*) as nbrUserAC
FROM `submission`
WHERE Status = 'AC'
GROUP BY users_ID) userDupli
on userDupli.users_ID = s.users_ID
WHERE
Status <> 'AC'
GROUP BY
users_ID
,userDupli.nbrUserAC

Related

How to create right query?

I'm trying write a query:
SELECT id FROM users WHERE status = 3
But if this sample returns an empty response, then I need instead to select the id where status = 4, and if it returns empty again, where status = 5.
How can I write a single query to solve this?
I think you simply want:
SELECT id
FROM users
WHERE status >= 3
ORDER BY status asc
LIMIT 1;
If you want multiple users:
SELECT u.id
FROM users u
WHERE u.status = (SELECT MIN(u2.status)
FROM users u2
WHERE u2.status >= 3
);
If you have a fixed list you want to test, you can also use:
select u.id
from users u
where u.status = 3
union all
select u.id
from users u
where u.status = 4 and
not exists (select 1 from users u2 where u2.status in (3))
union all
select u.id
from users u
where u.status = 5 and
not exists (select 1 from users u2 where u2.status in (3, 4));
You can use OR condition or use IN operator
SELECT id FROM users WHERE status = 3 or status = 3 or status = 5
or
SELECT id FROM users WHERE status IN (3,4,5)
I will use the case statement in the where clause:
select id
from users
where status = case when status = 3 and id is null then 4
when status = 4 and id is null then 5
else 3
end
Let me know if you have any question.
Assuming that your table look like this:
+----+--------+
| id | status |
+----+--------+
| 1 | 3 |
| 1 | 4 |
| 1 | 5 |
| 3 | 3 |
| 3 | 4 |
| 4 | 4 |
| 4 | 5 |
| 5 | 5 |
+----+--------+
And based on your condition where you want to see the lowest status first for each id, you can use MIN() operator.
So, from your original query:
SELECT id,MIN(status) FROM users GROUP BY id;
Then you'll get a result like this:
+----+-------------+
| id | MIN(status) |
+----+-------------+
| 1 | 3 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
+----+-------------+

Finding duplicates from two columns, but show all rows MySQL

I have a table like this
| user_id | company_id | employee_id |
|---------|------------|-------------|
| 1 | 2 | 123 |
| 2 | 2 | 123 |
| 3 | 5 | 432 |
| 4 | 5 | 432 |
| 5 | 7 | 432 |
I have a query that looks like this
SELECT COUNT(*) AS Repeated, employee_id, GROUP_CONCAT(user_id) as user_ids, GROUP_CONCAT(username)
FROM user_company
INNER JOIN user ON user.id = user_company.user_id
WHERE employee_id IS NOT NULL
AND user_company.deleted_at IS NULL
GROUP BY employee_id, company_id
HAVING Repeated >1;
The results I am getting look like this
| Repeated | employee_id | user_ids |
|---------|--------------|------------|
| 2 | 123 | 2,3 |
| 2 | 432 | 7,8 |
I need results that look like this
| user_id |
|---------|
| 2 |
| 3 |
| 7 |
| 8 |
I realize my query is getting more, but that's just to make sure I'm getting the correct data. Now I need to get a single column result with each user_id in a new row for updating based on user_id in another query. I've tried this by only selecting the user_id but I only get two rows, I need all four rows of duplicates.
Any ideas on how to modify my query?
Here is the query to get all of your user_ids:
SELECT user_id
FROM user_company uc
INNER JOIN
(
SELECT employee_id, company_id
FROM user_company
WHERE employee_id IS NOT NULL
AND deleted_at IS NULL
GROUP BY employee_id, company_id
HAVING COUNT(employee_id) >1
) AS `emps`
ON emps.employee_id = uc.`employee_id`
AND emps.company_id = uc.`company_id`;
This query below will generate the query you are looking for.
SELECT CONCAT('UPDATE user_company SET employee_id = null WHERE user_id IN (', GROUP_CONCAT(user_id SEPARATOR ', '),')') AS user_sql
FROM user_company uc
INNER JOIN
(SELECT employee_id, company_id
FROM user_company
WHERE employee_id IS NOT NULL
AND deleted_at IS NULL
GROUP BY employee_id, company_id
HAVING COUNT(employee_id) >1) AS `emps`
ON emps.employee_id = uc.`employee_id`
AND emps.company_id = uc.`company_id`;

How to select only the latest rows for each user?

My table looks like this:
id | user_id | period_id | completed_on
----------------------------------------
1 | 1 | 1 | 2010-01-01
2 | 2 | 1 | 2010-01-10
3 | 3 | 1 | 2010-01-13
4 | 1 | 2 | 2011-01-01
5 | 2 | 2 | 2011-01-03
6 | 2 | 3 | 2012-01-13
... | ... | ... | ...
I want to select only the latest users periods entries, bearing in mind that users will not all have the same period entries.
Essentially (assuming all I have is the above table) I want to get this:
id | user_id | period_id | completed_on
----------------------------------------
3 | 3 | 1 | 2010-01-13
4 | 1 | 2 | 2011-01-01
6 | 2 | 3 | 2012-01-13
Both of the below queries always resulted with the first user_id occurance being selected, not the latest (because the ordering happens after the rows are selected from what I understand):
SELECT
DISTINCT user_id,
period_id,
completed_on
FROM my_table
ORDER BY
user_id ASC,
period_id DESC
SELECT *
FROM my_table
GROUP BY user_id
ORDER BY
user_id ASC,
period_id DESC
Seems like this should work using MAX and a subquery:
SELECT t.Id, t.User_Id, t.Period_Id, t.Completed_On
FROM my_table t
JOIN (SELECT Max(completed_on) Max_Completed_On, t.User_Id
FROM my_table
GROUP BY t.User_ID
) t2 ON
t.User_Id = t2.User_Id AND t.Completed_On = t2.Max_Completed_On
However, if you potentially have multiple records where the completed_on date is the same per user, then this could return multiple records. Depending on your needs, potentially adding a MAX(Id) in your subquery and joining on that would work.
try this:
SELECT t.Id, t.User_Id, t.Period_Id, t.Completed_On
FROM table1 t
JOIN (SELECT Max(completed_on) Max_Completed_On, t.User_Id
FROM table1 t
GROUP BY t.User_ID) t2 ON t.User_Id = t2.User_Id AND t.Completed_On = t2.Max_Completed_On
DEMO HERE

Get similar queries from MySQL

How to make a query to get only records with the same screen_name and skip=0 value?
---------------------------
| id | screen_name | skip |
---------------------------
| 1 | mary | 0 |
| 2 | john | 0 |
| 3 | tom | 1 |
| 4 | mary | 0 |
| 5 | ben | 1 |
| 6 | john | 1 |
---------------------------
SELECT screen_Name
FROM tableName
WHERE skip = 0
GROUP BY screen_name
HAVING COUNT(*) > 1
SQLFiddle Demo
UPDATE
if you want to get all records not just the screen_name, use JOIN instead of IN
SELECT a.*
FROM tableName a
INNER JOIN
(
SELECT screen_Name
FROm tableName
WHERE skip = 0
GROUP BY screen_name
HAVING COUNT(*) > 1
) b ON a.screen_name = b.screen_name
SQLFiddle Demo
For faster performance, add an INDEX on column screen_name for faster performance.
ALTER TABLE tableName ADD INDEX index_name (screen_Name)
You coud try to use:
select id,screen_name,skip
from TABLE
where skip=0
and screen_name in (select t2.screen_name
from TABLE t2
group by t2.screen_name
having count(*)>1
)
This will give you all the records with skip=0 and a repeated screen_name

Getting COUNT while ignoring GROUP BY

I have the following table: ProductSales
+-------+-----------+--------+-----------+
|prod_id|customer_id|order_id|supplier_id|
+-------+-----------+--------+-----------+
| 1 | 1 | 1 | 1 |
+-------+-----------+--------+-----------+
| 2 | 4 | 2 | 2 |
+-------+-----------+--------+-----------+
| 3 | 1 | 1 | 1 |
+-------+-----------+--------+-----------+
| 4 | NULL | NULL | Null |
+-------+-----------+--------+-----------+
| 5 | 1 | 1 | 2 |
+-------+-----------+--------+-----------+
| 6 | 4 | 7 | 1 |
+-------+-----------+--------+-----------+
| 7 | 1 | 1 | 3 |
+-------+-----------+--------+-----------+
I have a SELECT query:
SELECT customer_id AS customer, count(*) AS prod_count
, count(DISTINCT order_id) as orders
FROM ProductSales
WHERE supplier_id=1
GROUP BY customer_id
HAVING customer_id<>'NULL'
This will be produce the result:
+--------+----------+------+
|customer|prod_count|orders|
+--------+----------+------+
| 1 | 2 | 1 |
+--------+----------+------+
| 4 | 1 | 1 |
+--------+----------+------+
What I have been trying to achieve and getting nowhere is to add a fourth column in my results to show the number of order_ids that belong only to the current supplier for each customer:
+--------+----------+------+-------------+
|customer|prod_count|orders|Unique Orders|
+--------+----------+------+-------------+
| 1 | 2 | 1 | 0 | } Order '1' is connected with two supplier_ids
+--------+----------+------+-------------+
| 4 | 1 | 1 | 1 | } Order '2' is connected to only one supplier_id
+--------+----------+------+-------------+
(This gets more complex when there are more orders per customer associated with far more suppliers).
I thought I was close with:
SELECT t1.user_id, count(DISTINCT t1.prod_id) AS prod_count
, count(DISTINCT t1.order_id) as orders
, IF(count(DISTINCT t3.supplier_id)>1,0,1) AS Unique_Orders
FROM ProductSales AS t1
LEFT JOIN `order` AS t2 ON t1.order_id=t2.order_id
LEFT JOIN ProductSales AS t3 ON t2.order_id=t3.order_id
WHERE t1.supplier_id=1
GROUP BY t1.customer_id
HAVING t1.customer_id<>'NULL'
The orders table stated above is related to ProductSales only by order_id.
Which shows my Customers, Products(total), Orders(total) but the Unique Orders shows if there are unique orders (0) or not (1), I understand the logic of the IF statement and it does what I expect. It's working out how to find the number of unique orders which is baffling me.
The table is established and can't be changed.
Any suggestions?
Unique orders can be defined as
SELECT OrderID
FROM yourtable
GROUP BY OrderID
Having COUNT(Distinct SupplierID) = 1
So try
SELECT
customer_id AS customer,
count(*) AS prod_count.
count(DISTINCT productsales.order_id) as orders,
COUNT(distinct uqo)
FROM ProductSales
left join
(
SELECT Order_ID uqo
FROM Productsales
GROUP BY Order_ID
Having COUNT(Distinct supplier_id) = 1
) uniqueorders
on ProductSales.order_id = uniqueorders.uqo
WHERE supplier_id=1
GROUP BY customer_id