In clause with And operation - mysql

I have records like this....
oid id
35 1
43 1
46 1
43 2
49 2
50 3
51 3
52 4
I have id=1 and 2 . I want those results which belong to both the both the ids(1,2) only.
i.e - o/p = recodrds of object_id = 43 because it is belonging to both 1 and 2.
if I use in operator then it is giving all the records (performing OR operaion)

This is a generic, fast solution to this kind of problems.
Get all IDs (in this case oid values) that staisfy our condition:
select oid from MyTalbe
where id in (1,2)
group by oid
having count (distinct id) >1
Select rows where IDs ('oid` column) IN list of IDs we need:
select oid, id from Mytable
where oid in
(select oid from MyTalbe
where id in (1,2) -- This is the same as: where id =1 or id=2
group by oid
having count (distinct id) >1
)

You can use the IN operator but then use a GROUP BY with a HAVING clause to return only those rows with a DISTINCT count of 2:
select oid
from yourtable
where id in (1,2)
group by oid
having count(distinct id) = 2;
--^ change this number to the count of ids in IN clause
See SQL Fiddle with Demo

Try this
SELECT t.oid FROM table1 t
WHERE t.oid IN (SELECT oid FROM table1 t1 WHERE t1.oid=t.oid AND t1.id = 1)
AND t.oid IN (SELECT oid FROM table1 t1 WHERE t1.oid=t.oid AND t1.id = 2)
GROUP BY oid

Related

Select all orders except the max order for each distinct customer

Sorry for the poor formatting but as part of a larger problem, I have created a query that produces this table:
id id2
4 7
4 6
1 3
1 2
1 1
How would I extract the rows that don't have the highest id2 for each id1.
What I want:
id id2
4 6
1 2
1 1
I can only seem to figure out how to get rid of the max id2 overall but not for each distinct id1. Any help on actually differentiating the max id2 for each id1 would be appreciated.
You can try below way -
select a.id, a.id2
from tablename a
where a.id2 <> (select max(a1.id2) from tablename a1 where a.id=a1.id)
If you are using MySQL 8+, then RANK() provides one option:
WITH cte AS (
SELECT id, id2, RANK() OVER (PARTITION BY id ORDER BY id2 DESC) rnk
FROM yourTable
)
SELECT id, id2
FROM cte
WHERE rnk > 1
ORDER BY id DESC, id2 DESC;
Demo
instead of a correlated subquery in the where, you can LEFT JOIN and apply not in...
select id, id2
from yourTable YT
LEFT JOIN
( select id, max( id2 ) highestID2
from YourTable
group by id ) TopPerID
on YT.ID = TopPerID.ID
AND YT.ID2 != TopPerID.highestID2
where TopPerID.id IS NULL
Since you can have id values with only one id2 value, you need to check for that situation as well, which you can do by comparing the MAX(id2) value with the MIN(id2) value in a JOIN:
SELECT t1.*
FROM Table1 t1
JOIN (SELECT id, MAX(id2) AS max_id2, MIN(id2) AS min_id2
FROM Table1
GROUP BY id) t2 ON t2.id = t1.id
AND (t1.id2 < t2.max_id2 OR t2.min_id2 = t2.max_id2)
If we add a row 2, 5 to your sample data this correctly gives the result as
id id2
4 6
1 2
1 1
2 5
Demo on SQLFiddle

Get count with having particular value associated with unique id

I Have below mentioned table:
ID Value
U-1 ACB
U-1 ART
U-1 DDD
U-2 ACB
U-2 DDD
U-3 XCC
U-3 DFC
I want to fetch those rows where Value is DDD but total count of unique ID is <3.
Required Output:
ID Value
U-2 ACB
U-2 DDD
You could use a self join to same table, Inner query will calculate count per id and filter rows where count is less than 3
select a.*
from table1 a
join (
select id, count(*) total
from table1
group by id
having total < 3
and sum(`Value` = 'DDD') > 0
) t using(id);
Demo
OR
select a.*
from table1 a
where (
select count(*)
from table1
where ID = a.ID
having sum(`Value` = 'DDD') > 0
) < 3
but i prefer join approach
updated demo
How about this?
SELECT * FROM
(SELECT * FROM sof t1
WHERE (SELECT COUNT(id) FROM sof t2 WHERE t2.id = t1.id) < 3) as temp2
WHERE id IN (SELECT id FROM sof WHERE value = 'DDD')
The input and output matches for your case at my end atleast.
Demo: http://rextester.com/AZLA7822

MySql: How to select rows where all values are the same?

I have a table like this:
name |id | state
name1 12 4
name1 12 4
name2 33 3
name2 33 4
...
I want to select every name and id from table where state is only 4, that means name1 is correct, because it only has two records with state 4 and nothing more. Meanwhile name2 is wrong, because it has record with state 4 and record with state 3.
You can use aggregation as shown below:
SELECT name, id
FROM your_table
GROUP BY name, id
HAVING SUM(state<>4)=0;
See a Demo on SQL Fiddle.
select name, id from mytable where id not in
(select distinct id from mytable where state <> 4)
you might need 2 sub queries .
select with group by name were state 4
select with group by name
compare the count if the count is same then select it
example : select name , count (name) from table where state = 4 as T1
select name , count (name) from table as T2
select T1.name from T1 and T2 where T2.count = T1.count
You can use not exists like this:
select distinct name, id
from table1 a
where not exists (select *
from table1 b
where a.id=b.id and state<>4)
In a more general case you can use count distinct (with not exists or with a join):
select distinct name, id
from table1 a
where not exists (
select *
from table1 b
where a.id=b.id
group by id
HAVING count(distinct state)>1)

Get lowest shared value in a one to many relationship table

I have a one to many relationship table.
I want to get the lowest other_id that is shared between multiple id's.
id other_id
5 5
5 6
5 7
6 6
6 7
7 7
I can do this by building an SQL statement dynamically with parts added for each additional id I want to query on. For example:
select * from (
select other_id from SomeTable where id = 5
) as a
inner join (
select other_id from SomeTable where id = 6
) as b
inner join (
select other_id from SomeTable where id = 7
) as c
on a.other_id = b.other_id
and a.other_id = c.other_id
Is there a better way to do this? More specifically, is there a way to do this that doesn't require a variable number of joins? I feel like this problem probably already has a name and better solutions.
My query gives me the number 7, which is what I want.
i dont have a mysql server to test it out at the moment, but try a "group by" statement:
select
other_id
from
SomeTable
group by
other_id having count(*) > 1
order by
other_id asc
limit 1
the lowest other_id shared between all ids
select other_id
from SomeTable
group by other_id
having count(distinct id) = 3
order by other_id limit 1
or dynamically
select other_id
from SomeTable
group by other_id
having count(distinct id) = (select count(distinct id) from SomeTable)
order by other_id limit 1
or if you want to look for the lowest other_id shared between specific ids
select other_id
from SomeTable
where id in (5,6,7)
group by other_id
having count(distinct id) = 3
order by other_id limit 1
Use MIN for simple query
SELECT MIN(other_id) FROM table
Though, there seems to be working solutions I want to add my version, just to show, how smart I am ;-)
SELECT other_id FROM SomeTable a INNER JOIN SomeTable b on a.other_id=b.other_id ORDER by other_id ASC LIMIT 1

Count duplicates records in Mysql table?

I have table with, folowing structure.
tbl
id name
1 AAA
2 BBB
3 BBB
4 BBB
5 AAA
6 CCC
select count(name) c from tbl
group by name having c >1
The query returning this result:
AAA(2) duplicate
BBB(3) duplicate
CCC(1) not duplicate
The names who are duplicates as AAA and BBB. The final result, who I want is count of this duplicate records.
Result should be like this:
Total duplicate products (2)
The approach is to have a nested query that has one line per duplicate, and an outer query returning just the count of the results of the inner query.
SELECT count(*) AS duplicate_count
FROM (
SELECT name FROM tbl
GROUP BY name HAVING COUNT(name) > 1
) AS t
Use IF statement to get your desired output:
SELECT name, COUNT(*) AS times, IF (COUNT(*)>1,"duplicated", "not duplicated") AS duplicated FROM <MY_TABLE> GROUP BY name
Output:
AAA 2 duplicated
BBB 3 duplicated
CCC 1 not duplicated
For List:
SELECT COUNT(`name`) AS adet, name
FROM `tbl` WHERE `status`=1 GROUP BY `name`
ORDER BY `adet` DESC
For Total Count:
SELECT COUNT(*) AS Total
FROM (SELECT COUNT(name) AS cou FROM tbl GROUP BY name HAVING cou>1 ) AS virtual_tbl
// Total: 5
why not just wrap this in a sub-query:
SELECT Count(*) TotalDups
FROM
(
select Name, Count(*)
from yourTable
group by name
having Count(*) > 1
) x
See SQL Fiddle with Demo
The accepted answer counts the number of rows that have duplicates, not the amount of duplicates. If you want to count the actual number of duplicates, use this:
SELECT COALESCE(SUM(rows) - count(1), 0) as dupes FROM(
SELECT COUNT(1) as rows
FROM `yourtable`
GROUP BY `name`
HAVING rows > 1
) x
What this does is total the duplicates in the group by, but then subtracts the amount of records that have duplicates. The reason is the group by total is not all duplicates, one record of each of those groupings is the unique row.
Fiddle: http://sqlfiddle.com/#!2/29639a/3
SQL code is:
SELECT VERSION_ID, PROJECT_ID, VERSION_NO, COUNT(VERSION_NO) AS dup_cnt
FROM MOVEMENTS
GROUP BY VERSION_NO
HAVING (dup_cnt > 1 && PROJECT_ID = 11660)
I'm using this query for my own table in PHP, but it only gives me one result whereas I'd like to the amount of duplicate per username, is that possible?
SELECT count(*) AS duplicate_count
FROM (
SELECT username FROM login_history
GROUP BY username HAVING COUNT(time) > 1
) AS t;