deleting all b,a from table mysql - mysql

I have a table with 3 fields as below
id a b
1 1 2
2 1 3
3 2 1
4 2 3
5 3 1
6 3 2
(a,b) and (b,a) both exist in this table ( a=1 and b=2 and a=2 and b=1). i need to remove all (b,a) from the above table .
Output:
id a b
1 1 2
2 1 3
4 2 3
i tried a self join like this
select v1.id, v2.id from val v1,val v2 where v1.a=v2.b and v1.b=v2.a
and found out the corresponding ids which match. But , not able to proceed after this. Pls help.

If you want to permanently delete those duplicate records, here's the DELETE statement which uses MySQL's LEAST and GREATEST built-in functions.
DELETE a
FROM tableName a
LEFT JOIN
(
SELECT LEAST(a, b) aa,
GREATEST(a,b) bb,
MIN(ID) min_ID
FROM tableName
GROUP BY aa, bb
) b ON a.ID = b.min_ID
WHERE b.min_ID IS NULL
SQLFiddle Demo
the SELECT statement
SELECT *
FROM tableName
WHERE (LEAST(a, b),GREATEST(a,b), ID)
IN
(
SELECT LEAST(a, b) aa,
GREATEST(a,b) bb,
MIN(ID) min_ID
FROM tableName
GROUP BY aa, bb
)
SQLFiddle Demo

You could do this to select the output you want.
select id, v1.a, v2.a from test v1 left join test v2 on (v1.id = v2.id and v1.a > v2.b)
where v2.id is null

If you want to only show the "half" results:
SELECT *
FROM val
WHERE a <= b ;
and if you want to delete the other half:
DELETE *
FROM val
WHERE a > b ;

Related

how to exclude first and last row if group it on particular id

I have sample table with data like this
id uniqueid values
1 6 0
2 6 1
3 6 2
4 6 0
5 6 1
I want result like this
id uniqueid values
2 6 1
3 6 2
4 6 0
I tried like this
select id,uniqueid,values
FROM t1
WHERE
id not in(SELECT concat(MAX(message_id_pk),',',min(message_id_pk)) FROM t1
where uniqueid=6)
and `uniqueid`=6
GROUP BY uniqueid
but its not working
You can achieve the desired results by doing self join, Inner query will get the the max and min ids for per group and outer query will filter out the results by using minid and maxid
select a.*
from demo a
join (
select `uniqueid`,min(id) minid, max(id) maxid
from demo
where uniqueid=6
group by `uniqueid`
) b using(`uniqueid`)
where a.id > b.minid and a.id < b.maxid /* a.id <> b.minid and a.id <> b.maxid */
Demo
Also you can do it by using 2 sub-queries with EXISTS to exclude the min and max id of each uniqueid.
Query
select `id`, `uniqueid`, `values`
from `your_table_name` t1
where exists (
select 1 from `your_table_name` t2
where t2.`uniqueid` = t1.`uniqueid`
and t2.`id` > t1.`id`
)
and exists(
select 1 from `your_table_name` t2
where t2.`uniqueid` = t1.`uniqueid`
and t2.`id` < t1.`id`
);
Here is a sql fiddle demo
Try this -
SELECT id, uniqueid, values
FROM YOUR_TABLE
WHERE id NOT IN (MIN(id), MAX(id));

MySQL Count distinct values from one column

I have a table having three columns:
A B C
1 2 2
2 2 2
3 1 1
4 1 2
I want the count of those values which have C equal to 2 but with distinct values of B
So in this case for C = 2, count = 2 (B=2 and B=1)
I used the following command:
Select count(*) from mytable where C=2 group by (B)
but it yields:
count(*)
3
I have tried using "distinct" but it can't be use to select from one column
Have you tried
SELECT COUNT(DISTINCT B) FROM mytable WHERE C = 2;
Use sub query like this:
Select count(*) from (
select distinct B where c=2
)

SQL Query - Find Duplicates with a Different Key

I have the following data:
id userid name group
1 1 A x
2 1 A y
3 1 A z
4 2 B x
5 2 B y
6 3 C y
7 4 D x
8 5 E x
9 5 E z
10 6 F x
I want to find those records that meet all this condition:
Select all rows where the a userid belongs to a group other than y but the userid also belongs to group y.
The resulting dataset will be as follows:
id userid name group
1 1 A x
3 1 A z
4 2 B x
If you see, it has resulted in two records for userid a because these are two two records belong to groups other than y but the userid 1 also belongs to group y. Same for userid 2.
I have been breaking my head on how to get this in an SQL statement but not even close to a solution.
Any help is appreciated.
Use a join:
SELECT t1.*
FROM mytable t1
INNER JOIN mytable t2
ON t1.user_id = t2.user_id AND t1.group <> t2.group AND t2.group = 'y'
I think that would be the fastest query (but please feel free to try the other solutions as well).
Add an index on user_id if not already there and maybe play with some other indexes as well (maybe a composite index on group and user_id can be utilized)
Use exists
select *
from MyTable a2
where name_group <> 'y'
and exists (select 1
from MyTable a2
where a2.name_group = 'y'
and a2.userid = a1.userid)
You can get all the users that meet the condition using aggregation and having:
select userid
from t
group by userid
having sum( group = 'y' ) > 0 and
sum( group <> 'y') > 0;
I leave it to your to put this into a query to get all the original rows.

JOIN, GROUP BY, SUM Issue Mysql

Assuming I have this table
tableA
ID value
1 5
1 5
3 10
2 4
2 2
1 2
tableB
ID Name
1 apple
2 carrot
3 banana
If the expected max value of apple is 10, carrot is 5, and banana is 15 the output table would be
table output
ID Name value
1 apple 12
2 carrot 6
what SQL statement I need to solve this?
what I have done so far:
SELECT a,ID, b.name , sum(a.valueSUM) AS value FROM tableA a
INNER JOIN tableB b
ON a.id = b.id
GROUP BY id
what options i need on the WHERE clause to pull this off?
The inner subquery groups them normally and then the main query is what deals with limiting the results.
SELECT * FROM
(select
b.id,
b.name as name,
SUM(a.value) as the_sum
from tableA a inner join tableB b
on a.Id = b.id
group by b.name, b.id
) y
where (name = 'apple' and the_sum >= 10) OR
(name = 'banana' and the_sum >= 15) OR
(name = 'carrot' and the_sum >= 5)
It seems your sample data has changed, please try this. I thought the ID doesnt have to follow tableA/tableB's id and the id is auto-generated as per the results.
Would be nice if you have another table that sets the threshold per name
Assuming threshold can be specified in tableB (makes sense):
SELECT a.ID, b.name, sum(a.value) AS value
FROM tableA a
INNER JOIN tableB b
ON a.id = b.id
GROUP BY a.ID, b.name, b.Threshold
HAVING sum(a.value) > b.Threshold;
Demo: http://rextester.com/ICOQF10295
SELECT TableB.id, TableB.Name, MAX(TableA.value) AS Value
FROM TableA INNER JOIN TableB ON
TableA.id = TableB.id
GROUP BY TableB.id, TableB.Name
Instead of SUM, use MAX aggregate function
This works in SQL Server
--Existing tables
create table #tableA (ID int, value int)
create table #tableB (ID int, Name varchar(30))
insert into #tableA
select 1 , 5 union all
select 1 , 5 union all
select 3 , 10 union all
select 2 , 4 union all
select 2 , 2 union all
select 1 , 2
insert into #tableB
select 1 , 'apple' union all
select 2 , 'carrot' union all
select 3 , 'banana'
--Create new temporary table #tableC
create table #tableC (ID int, MAXvalue int)
insert into #tableC
select 1 , 10 union all
select 2 , 5 union all
select 3 , 15
select c.ID,b.Name, a.value from #tableC c
inner join #tableB b on b.ID = c.ID
inner join (
select ID,SUM(value) as value from #tableA
group by ID
) a on a.ID = c.ID
where a.value >= c.MAXvalue
drop table #tableA
drop table #tableB
drop table #tableC

Insert rows from one table to another but only those rows that have no duplicates

I've seen this, this, this, this and this but my question is different.
I have a Table1:
id c a b rc bid
1 12 4 6 35 4
2 12 4 6 67 7
3 12 4 6 88 8
4 23 4 7 49 3
5 23 5 8 59 8
Table2 also has the same columns but does not have bid column.
A row is considered a duplicate if it has the same values of columns c, a and b. So rows 1, 2 and 3 are considered duplicates because they have 12, 4 and 6.
I want to insert rows of Table1 to Table2, but only those rows that are not duplicates. Which means that rows 1, 2 and 3 won't get inserted to Table2. Only rows 4 and 5 will get inserted because they have no duplicates.
So Table2 will look like this after the inserts:
id c a b rc
1 23 4 7 49
2 23 5 8 59
I know I can get which rows have no duplicates using this query:
select distinct c,a,b,count(*) from Table1 group by c,a,b having count(*) > 1
But am not able to figure out how to insert these to Table2 because the insertion requires specific columns to be specified.
Tried something like this which obviously doesn't work:
insert into Table2 (c, a, b, rc) select distinct c,a,b,count(*) from Table1 group by c,a,b having count(*) > 1
You can use also not in in subselect
INSERT INTO Table2(c, a, b, rc, bid)
SELECT c, a, b, rc, bid
FROM Table1 t1
WHERE (c,a,b) not in ( SELECT c,a,b
FROM Table1 t2
GROUP BY c, a, b
HAVING COUNT(*) > 1
)
You can use NOT EXISTS to exclude duplicate rows:
INSERT INTO Table2(c, a, b, rc, bid)
SELECT
c, a, b, rc, bid
FROM Table1 t1
WHERE NOT EXISTS(
SELECT 1
FROM Table1 t2
WHERE
t2.c = t1.c
AND t2.a = t1.a
AND t2.b = t1.b
HAVING COUNT(*) > 1
)
The HAVING COUNT(*) > 1 will check if there are duplicates.
insert into table2 (c,a,b,rc)
select c,a,b,rc from table1
where id in (select distinct id
from Table1 group by c,a,b having count(*) = 1)
There are many ways to do that. You have already got so many correct answers. Here, I am giving the query based on the way you approached.
INSERT INTO Table2 (c, a, b, rc)
SELECT
c,
a,
b,
rc
FROM
Table1
GROUP BY c, a, b
HAVING count(*) = 1;