My working query is below. However, the results from that query will produce duplicates AND non duplicates on name column. I want to be able to only show results where name columns from the two select queries are different
select t.*
from tbl_user_tmp t JOIN
(select activity, class, count(*) as NumDuplicates
from tbl_user_tmp
where user = 'bignadad2'
group by activity, class
having NumDuplicates > 1)
tsum ON t.activity = tsum.activity and t.class = tsum.class
columns are in this order
id, name, activity, class, activity_id
I only want to show these results where activity, class match and name does not.
2059 lg_lmk com.lge.lmk com.lge.lmk.activities.LmkMainActivity 48255
3668 task_manager com.lge.lmk com.lge.lmk.activities.LmkMainActivity 48255
These are the other results i do not want to see
2690 phone com.modoohut.dialer com.modoohut.dialer.DialActivity 54700
2694 phone com.modoohut.dialer com.modoohut.dialer.DialActivity 54700
I forgot that you needs only some results
SELECT * FROM tbl_user_tmp AS t1
INNER JOIN (
SELECT activity, class, COUNT(1) AS cnt FROM tbl_user_tmp
WHERE user = 'first'
GROUP BY activity, class
HAVING cnt > 1
) AS t2
ON t1.activity = t2.activity AND t1.class = t2.class
WHERE user = 'first' -- remove records of the other users
GROUP BY t1.name, t1.activity, t1.class -- select distinct records
SQLFiddle
If class is unique in the activity then you can remove activity from the GROUP BY-statement.
Related
I have table like this one:
I would like to all rows, but if there is user_id 5 if this case, override other rows which have no user_id.
I tried both with MAX(user_id) and GROUP BY country_name, but it still returns, wrong results.
Final result I'm expecting:
Try this;)
select t1.*
from yourtable t1
inner join (
select max(user_id) as user_id, country_name from yourtable group by country_name
) t2 on t1.country_name = t2.country_name and t1.user_id = t2.user_id
This is just a solution based on your sample data. If you have a variety of user_id, it should be more different.
As of SQL Select only rows with Max Value on a Column you can easily get rows with max value on a column by using both MAX(column) and GROUP BY other_column in one statement.
But if you want to select other columns too, you have to this in a subquery like in the following example:
SELECT a.*
FROM YourTable a
INNER JOIN (
SELECT country_name, MAX(user_id) user_id
FROM YourTable
GROUP BY country_name
) b ON a.country_name = b.country_name AND a.user_id = b.user_id
I have three tables:
user: id, name
keyword: id, name
userkeyword: id, user_id, keyword_id
I want to execute query in following way:
Display those users whose keyword/s are matched with the login user's
keywords. In the order of maximum number of keyword matched user
should display first
e.g : If userA having 4 matched keywords, userB having 8, userC having 1, userD having 6 then the result should be in the order of,
userB
userD
userA
userC
For that I have done with this query (assume login user's id is 1):
select *
from user
where id IN (
select user_id
from userkeywords
where keyword_id IN (
select keyword_id
from userkeywords
where user_id=1)
group by user_id
order by count(keyword_id) desc)
AND id != 1
Here the result is getting perfect but the order is not correct. I have merged two queries in following manner"
select *
from user
where id IN (?)
AND id!=1
+
select user_id
from userkeywords
where keyword_id IN (
select keyword_id
from userkeywords
where user_id=1)
group by user_id
order by count(keyword_id) desc
Second query returns user_id in correct order but when I merged both queries, order was changed (wrong).
Hope I have mentioned my query properly with enough detail.
A subquery returns an unordered set, so the order by in a subquery only matters for its limit clause, if there is any. Any database other than MySQL would give an error message for a purely decorative sort order.
There's no way to sort on a column that only exists in the where clause. You'd have to rewrite the query. One option is to replace your in conditions with joins:
select uk2.name
from userkeywords uk1
join userkeywords uk2
on uk1.keyword_id = uk2.keyword_id
and uk1.user_id <> uk2.user_id
join user u2
on u2.id = uk2.user_id
where uk1.user_id = 1
group by
uk2.name
order by
count(*) desc
This should do it.
select uk.user_id, u.name
from userkeywords uk
left join user u on u.id = uk.user_id
where uk.keyword_id IN (
select keyword_id
from userkeywords
where user_id=1)
group by uk.user_id
order by count(uk.keyword_id) desc) AND uk.user_id != 1
Also, JOIN provides better performance.
I would use an inner join to select the correct rows:
SELECT *
FROM user
INNER JOIN (
SELECT * FROM userkeyword
WHERE keyword_id IN (
SELECT keyword_id
FROM userkeyword
WHERE user_id=1
)
) uk
ON user.id = uk.user_id
GROUP BY u.id
ORDER BY count(*) DESC;
I have a table in SQL that is a list of users checking in to a website. It looks much like this:
id | date | status
------------------
Status can be 0 for not checking in, 1 for checked in, 2 for covered, and 3 for absent.
I'm trying to build one single query that lists all rows with status = 0, but also has a COUNT on how many rows have status = 3 on each particular id.
Is this possible?
MySQL VERSION
just join a count that is joined by id.
SELECT t.*, COALESCE(t1.status_3_count, 0) as status_3_count
FROM yourtable t
LEFT JOIN
( SELECT id, SUM(status=3) as status_3_count
FROM yourtable
GROUP BY id
) t1 ON t1.id = t.id
WHERE t.status = 0
note: this is doing the boolean sum (aka count)..
the expression returns either true or false a 1 or a 0. so I sum those up to return the count of status = 3 for each id
SQL SERVER VERSION
SELECT id, SUM(CASE WHEN status = 3 THEN 1 ELSE 0 END) as status_3_count
FROM yourtable
GROUP BY id
or just use a WHERE status = 3 and a COUNT(id)
Try a dependent subquery:
SELECT t1.*,
( SELECT count(*)
FROM sometable t2
WHERE t2.id = t1.id
AND t2.status = 3
) As somecolumnname
FROM sometable t1
WHERE t1.status=0
You can use a join for this. Write one query that will get all rows with a status zero:
SELECT *
FROM myTable
WHERE status = 0;
Then, write a subquery to get counts for the status of 3 for each id, by grouping by id:
SELECT COUNT(*)
FROM myTable
WHERE status = 3
GROUP BY id;
Since you want all the rows from the first table (at least that's what I am picturing), you can use a LEFT JOIN with the second table like this:
SELECT m.id, m.status, IFNULL(t.numStatus3, 0)
FROM myTable m
LEFT JOIN (SELECT id, COUNT(*) AS numStatus3
FROM myTable
WHERE status = 3
GROUP BY id) t ON m.id = t.id
WHERE m.status = 0;
The above will only show the count for rows containing an id that has status 0. Hopefully this is what you are looking for. If it is not, please post some sample data and expected results and I will help you try to reach it. Here is an SQL Fiddle example.
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
I have the query below that shows me duplicates in my table. I would like to know how can i turn this into a delete query to delete these duplicate rows but leaving just one. My table does have a auto increment id column.
SELECT * FROM tbl_user_tmp AS t1
INNER JOIN (
SELECT name, activity, class, COUNT(1) AS cnt FROM tbl_user_tmp
WHERE user = 'test' AND disregard = 0
GROUP BY name, activity, class
HAVING cnt > 1
) AS t2
ON t1.name = t2.name AND t1.activity = t2.activity AND t1.class = t2.class
WHERE user = 'test' AND disregard = 0
GROUP BY t1.name, t1.activity, t1.class
I have tried the query below and seems to work, but im afraid im missing something. does it look correct?
delete from tbl_user_tmp
where user='test' AND id not in
(
select minid from
(select min(id) as minid from tbl_user_tmp where user='test' group by name, activity, class) as newtable
)
You can use LIMIT.
Example:
DELETE FROM users
LIMIT 2;
Now you just need to set COUNT - 1 as your limit ;)