Finding Connection Pairs - mysql

Suppose we have a table in mySQL database where fname has a connection to another fname(BB_Connection_name), we would like have a query to find the pair(s) of friends who find connection among themselves.
E.g
Sidharth and Asim both have each others BBid and BB_Connection_ID
I have looked for similar case of father, son and grandson question but in that not each father has a son and thus inner joining them makes things easier for solving. I tried using that but didn't work.
Here i need to check BB_Connection_ID for every fname(A) and then corresponding fname has A's BBid as his BB_Connection_ID or not.
The pairs which would be chosen, should be like Sidharth<->Asim
We need to find the pairs who have their connection ID to each other.
==========================================================================
Code for recreation of the table:
-----------------------------------------------------------------------------
create table world.bigbb(
BBid int not null auto_increment,
fname varchar(20) NOT NULL,
lname varchar(30),
BBdays int not null,
No_of_Nom int,
BB_rank int not null,
BB_Task varchar(10),
BB_Connection_ID int,
BB_Connection_name varchar(10),
primary key (BBid)
);
insert into world.bigbb (fname, lname, BBdays, No_of_Nom, BB_rank, BB_Task, BB_Connection_ID, BB_Connection_name)
values
('Sidharth', 'Shukla', 40, 4, 2, 'Kitchen', 11, 'Asim'),
('Arhaan', 'Khan', 7, 1, 9, 'Kitchen', 16, 'Rashmi'),
('Vikas', 'Bhau', 7, 1, 8, 'Bedroom', 11, 'Asim'),
('Khesari', 'Bihari', 7, 1, 12, 'Kitchen', 9, 'Paras'),
('Tehseem', 'Poonawala', 7, 1, 11, 'Washroom', 12, 'Khesari'),
('Shehnaaz', 'Gill', 40, 4, 4, 'Washroom', 9, 'Paras'),
('Himanshi', 'Khurana', 7, 0, 7, 'Bedroom', 8, 'Shefali'),
('Shefali', 'Zariwala', 7, 1, 10, 'Bedroom', 1, 'Sidharth'),
('Paras', 'Chabra', 40, 3, 1, 'Bathroom', 10, 'Mahira'),
('Mahira', 'Sharma', 40, 4, 5, 'Kitchen', 9, 'Paras'),
('Asim', 'Khan', 40, 3, 3, 'Bathroom', 1, 'Sidharth'),
('Arti', 'Singh', 40, 5, 6, 'Captain', 1, 'Sidharth'),
('Sidharth', 'Dey', 35, 6, 16, 'None', 14, 'Shefali'),
('Shefali', 'Bagga', 38, 5, 15, 'None', 13, 'Sidharth'),
('Abu', 'Fifi', 22, 5, 17, 'None', 11, 'Asim'),
('Rashmi', 'Desai', 38, 5, 13, 'None', 17, 'Debolina'),
('Debolina', 'Bhattacharjee', 38, 5, 14, 'None', 16, 'Rashmi');

One solution would be to self-join the table:
select
b1.fname name1,
b2.fname name2
from bigbb b1
inner join bigbb b2
on b1.BB_Connection_ID = b2.BBid
and b2.BB_Connection_ID = b1.BBid
and b1.BBid < b2.BBid
This will give you one record for each pair, with the record having the smallest BBid in the first column.
This demo on DB Fiddle with your sample data returns:
name1 | name2
:------- | :-------
Sidharth | Asim
Paras | Mahira
Sidharth | Shefali
Rashmi | Debolina

Related

Return list of users

I have entity like this
{
id,
projectId,
name,
age,
address
}
Now I need to return list of users that are connected to projects which have 4 or more users
For example if I have in database records like this
{1, 1, "John", 21, "Address1"}
{2, 1, "Joey", 22, "Address2"}
{3, 2, "Tom", 25, "Address3"}
{4, 3, "Mike", 23, "Address4"}
{5, 1, "John", 26, "Address5"}
{6, 3, "Jane", 28, "Address6"}
{7, 2, "Joe", 23, "Address7"}
{8, 2, "Steve", 24, "Address8"}
{9, 3, "Will", 29, "Address9"}
{10, 1, "Robert", 21, "Address10"}
{11, 2, "James", 20, "Address11"}
i should get returned list
{1, 1, "John", 21, "Address1"}
{2, 1, "Joey", 22, "Address2"}
{3, 2, "Tom", 25, "Address3"}
{5, 1, "John", 26, "Address5"}
{7, 2, "Joe", 23, "Address7"}
{8, 2, "Steve", 24, "Address8"}
{10, 1, "Robert", 21, "Address10"}
{11, 2, "James", 20, "Address11"}
because project with ID 1 have 4 users and also project with ID 2 have 4 users, but project with ID 3 have 3 users and I don't need that users as result.
I'm using SpringData JPA but as I researched JPA doesn't provide option to make such filtering and as other option I found that I can write custom MySql Query but don't know how that query should look like
I've tried something with group by projectId but don't know how to count and get only groups that have 4 or more users
#Query(value = "SELECT * FROM USER u GROUP BY projectId", nativeQuery = true)
List<User> findUsers();
create table temp (
id int,
projectId int,
name varchar(20),
age int,
address varchar(20)
);
insert into temp (id,projectId,name,age,address) values (1, 1, 'John', 21, 'Address1');
insert into temp (id,projectId,name,age,address) values (2, 1, 'Joey', 22, 'Address2');
insert into temp (id,projectId,name,age,address) values (3, 2, 'Tom', 25, 'Address3');
insert into temp (id,projectId,name,age,address) values (4, 3, 'Mike', 23, 'Address4');
insert into temp (id,projectId,name,age,address) values (5, 1, 'John', 26, 'Address5');
insert into temp (id,projectId,name,age,address) values (6, 3, 'Jane', 28, 'Address6');
insert into temp (id,projectId,name,age,address) values (7, 2, 'Joe', 23, 'Address7');
insert into temp (id,projectId,name,age,address) values (8, 2, 'Steve', 24, 'Address8');
insert into temp (id,projectId,name,age,address) values (9, 3, 'Will', 29, 'Address9');
insert into temp (id,projectId,name,age,address) values (10, 1, 'Robert', 21, 'Address10');
insert into temp (id,projectId,name,age,address) values (11, 2, 'James', 20, 'Address11');
QUERY :
SELECT *
FROM temp
WHERE projectid IN (SELECT projectid
FROM temp
GROUP BY projectid
HAVING Count(*) > 3)

Need mysql query to find total sum as per matched query

I need to find sum of specific columns as per matched some of columns value in database table.
Please check mysql table that i use :
CREATE TABLE IF NOT EXISTS `plant_production_items` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`plant_production_id` int(11) NOT NULL,
`materialid` int(11) NOT NULL,
`packaging_id` int(11) NOT NULL,
`grade_id` int(11) NOT NULL,
`slabs` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `material_purchase_id` (`plant_production_id`),
KEY `grade_id` (`grade_id`),
KEY `packaging_id` (`packaging_id`),
KEY `slabs` (`slabs`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=104 ;
Value are as under :
INSERT INTO `plant_production_items` (`id`, `plant_production_id`, `materialid`, `packaging_id`, `grade_id`, `slabs`) VALUES
(5, 4, 22, 85, 29, 4444),
(6, 5, 22, 14, 25, 3234),
(8, 6, 27, 21, 60, 4444),
(11, 8, 22, 85, 29, 44444),
(19, 7, 22, 84, 29, 434),
(75, 10, 26, 0, 51, 1233),
(76, 10, 24, 17, 34, 251),
(78, 10, 26, 0, 46, 3234),
(91, 9, 27, 21, 57, 1000),
(92, 9, 27, 21, 57, 2000),
(93, 3, 23, 16, 32, 5000),
(94, 3, 27, 21, 54, 3233),
(101, 3, 27, 21, 0, 700),
(103, 3, 29, 27, 0, 6666);
I want total sum of 'slabs' columns as per unique value founded in following column :
plant_production_id
materialid
packaging_id
grade_id
In short we need to find combination of all 4 values of above and need to show total sum of 'slabs' column.
For example :
there are two records which are same:
(91, 9, 27, 21, 57, 1000),
(92, 9, 27, 21, 57, 2000),
so here i want to get total sum i.e 1000+2000 = 3000
Out put should be all columns with total slabs. It is not required we need to match all above 4 columns. Actually we need to find all total slabs as per total records found same with above 4 column.
If still not clear then let me know.
You can use GROUP BY like this:
SELECT
plant_production_id,
materialidm,
packaging_id,
grade_id,
SUM(`slabs`) slabs_sum
FROM plant_production_items
GROUP BY plant_production_id, materialidm, packaging_id, grade_id;
So it gives the sum of the slabs for rows with the same values for columns grouped by.

Update query from multiple tables, for specific IDs and JOIN LIMIT 1

I have two tables, and I want to update the rows of torrents from scrapes every day.
scrapes:
id, torrent_id, name, status, complete, incomplete, downloaded
1, 1, http://tracker1.com, 1, 542, 23, 542
2, 1, http://tracker2.com, 1, 542, 23, 542
3, 2, http://tracker1.com, 1, 123, 34, 43
4, 2, http://tracker2.com, 1, 123, 34, 43
5, 3, http://tracker1.com, 1, 542, 23, 542
6, 3, http://tracker2.com, 1, 542, 23, 542
7, 4, http://tracker1.com, 1, 123, 34, 43
8, 4, http://tracker2.com, 1, 123, 34, 43
9, 5, http://tracker1.com, 1, 542, 23, 542
10, 5, http://tracker2.com, 1, 542, 23, 542
11, 6, http://tracker1.com, 1, 123, 34, 43
12, 6, http://tracker2.com, 1, 123, 34, 43
torrents:
id, name, complete, incomplete, downloaded
1, CentOS, 0, 0, 0
2, Ubuntu, 0, 0, 0
3, Debian, 0, 0, 0
4, Redhat, 0, 0, 0
5, Fedora, 0, 0, 0
6, Gentoo, 0, 0, 0
The scrapes may have multiple name, but I want to get the values only from the first found (for better performance) and also, I need to update only torrents ids 1, 3, 6 on one query.
UPDATE (SELECT * FROM scrapes WHERE torrent_id IN(1,3,6) GROUP BY torrent_id) as `myview` JOIN torrents ON myview.torrent_id=torrents.id SET torrent.complete=myview.complete WHERE 1

MYSQL Join/Index optimization

I have a query that tries to find all shopping carts containing a set of given packages.
For each package I join the corresponding cartitem table once, because I am only interested in carts containing all given packages.
When I reach more than 15 packages(joins) the query performance rapidly drops.
I have two indeces on the corresponding foreign columns and am aware that mysql uses only one of them. When I add an index over the 2 columns(cartitem_package_id,cartitem_cart_id) it works, but is this the only way to solve this situation?
I would like to know why MYSQL suddently stucks in this situation and what may be the mysql internal problem, because I do not see any deeper problem with this definition and query? Does that may be an issue with the query optimizer and can I do something(e.g. adding brackets) to support or force a specific query execution? Or has anyone a different approach here, using another query?
The query looks something like this:
SELECT cart_id
FROM cart
INNER JOIN cartitem as c1 ON cart_id=c1.cartitem_cart_id AND c1.cartitem_package_id= 7
INNER JOIN cartitem as c2 ON cart_id=c2.cartitem_cart_id AND c2.cartitem_package_id= 8
INNER JOIN cartitem as c3 ON cart_id=c3.cartitem_cart_id AND c3.cartitem_package_id= 9
INNER JOIN cartitem as c4 ON cart_id=c4.cartitem_cart_id AND c4.cartitem_package_id= 10
INNER JOIN cartitem as c5 ON cart_id=c5.cartitem_cart_id AND c5.cartitem_package_id= 11
INNER JOIN cartitem as c6 ON cart_id=c6.cartitem_cart_id AND c6.cartitem_package_id= 12
INNER JOIN cartitem as c7 ON cart_id=c7.cartitem_cart_id AND c7.cartitem_package_id= 13
INNER JOIN cartitem as c8 ON cart_id=c8.cartitem_cart_id AND c8.cartitem_package_id= 14
INNER JOIN cartitem as c9 ON cart_id=c9.cartitem_cart_id AND c9.cartitem_package_id= 15
INNER JOIN cartitem as c10 ON cart_id=c10.cartitem_cart_id AND c10.cartitem_package_id= 16
INNER JOIN cartitem as c11 ON cart_id=c11.cartitem_cart_id AND c11.cartitem_package_id= 17
INNER JOIN cartitem as c12 ON cart_id=c12.cartitem_cart_id AND c12.cartitem_package_id= 18
INNER JOIN cartitem as c13 ON cart_id=c13.cartitem_cart_id AND c13.cartitem_package_id= 19
INNER JOIN cartitem as c14 ON cart_id=c14.cartitem_cart_id AND c14.cartitem_package_id= 20
INNER JOIN cartitem as c15 ON cart_id=c15.cartitem_cart_id AND c15.cartitem_package_id= 21
INNER JOIN cartitem as c16 ON cart_id=c16.cartitem_cart_id AND c16.cartitem_package_id= 22
INNER JOIN cartitem as c17 ON cart_id=c17.cartitem_cart_id AND c17.cartitem_package_id= 23
Output:
No result.
Consider the following sample structure:
CREATE TABLE IF NOT EXISTS `cart` (
`cart_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`cart_state` smallint(20) DEFAULT NULL,
PRIMARY KEY (`cart_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=80 ;
INSERT INTO `cart` (`cart_id`, `cart_state`) VALUES
(1, 0),(2, 5),(3, 0),(4, 0),(5, 0),(6, 0),(7, 0),(8, 0),(9, 0),(10, 0),(11, 0),(12, 0),(13, 0),(14, 5),(15, 5),(16, 10),(17, 0),(18, 10),(19, 40),(20, 10),(21, 5),(22, 0),(23, 10),(24, 10),(25, 0),(26, 10),(27, 5),(28, 5),(29, 0),(30, 5),(31, 0),(32, 0),(33, 0),(34, 0),(35, 0),(36, 0),(37, 0),(38, 0),(39, 0),(40, 0),(41, 0),(42, 0),(43, 0),(44, 0),(45, 40),(46, 0),(47, 0),(48, 1),(49, 0),(50, 5),(51, 0),(52, 0),(53, 5),(54, 5),(55, 0),(56, 0),(57, 10),(58, 0),(59, 0),(60, 5),(61, 0),(62, 0),(63, 10),(64, 0),(65, 5),(66, 5),(67, 10),(68, 10),(69, 0),(70, 0),(71, 10),(72, 0),(73, 10),(74, 0),(75, 10),(76, 0),(77, 10),(78, 0),(79, 10);
CREATE TABLE IF NOT EXISTS `cartitem` (
`cartitem_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`cartitem_package_id` int(10) unsigned DEFAULT NULL,
`cartitem_cart_id` int(10) unsigned DEFAULT NULL,
`cartitem_price` decimal(7,2) NOT NULL DEFAULT '0.00',
PRIMARY KEY (`cartitem_id`),
KEY `cartitem_package_id` (`cartitem_package_id`),
KEY `cartitem_cart_id` (`cartitem_cart_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=89 ;
INSERT INTO `cartitem` (`cartitem_id`, `cartitem_package_id`, `cartitem_cart_id`, `cartitem_price`) VALUES
(1, 4, 2, 200.00),(2, 7, 3, 30.00),(3, 14, 9, 255.00),(4, 14, 9, 255.00),(5, 22, 9, 120.00),(6, 22, 9, 120.00),(7, 13, 13, 300.00),(8, 13, 13, 300.00),(9, 7, 14, 450.00),(10, 13, 14, 250.00),(11, 17, 14, 150.00),(12, 7, 15, 450.00),(13, 13, 15, 250.00),(14, 18, 15, 127.50),(15, 7, 16, 450.00),(16, 17, 16, 150.00),(17, 7, 18, 450.00),(18, 7, 19, 450.00),(19, 17, 19, 150.00),(20, 21, 19, 25.00),(21, 13, 20, 300.00),(22, 7, 21, 550.00),(23, 19, 21, 105.00),(24, 22, 21, 120.00),(25, 17, 22, 150.00),(26, 7, 23, 550.00),(27, 11, 24, 245.00),(31, 7, 26, 450.00),(32, 21, 26, 25.00),(33, 21, 26, 25.00),(34, 22, 26, 120.00),(35, 23, 26, 120.00),(36, 10, 27, 382.50),(37, 22, 27, 120.00),(38, 13, 27, 250.00),(39, 10, 28, 297.50),(43, 7, 29, 550.00),(41, 20, 28, 82.50),(42, 22, 28, 120.00),(44, 7, 30, 550.00),(46, 22, 30, 120.00),(47, 23, 30, 120.00),(48, 21, 18, 25.00),(49, 21, 19, 25.00),(50, 17, 37, 150.00),(51, 17, 37, 150.00),(52, 21, 37, 25.00),(53, 21, 37, 25.00),(54, 4, 45, 1.20),(55, 6, 45, 0.00),(56, 7, 47, 450.00),(57, 4, 50, 200.00),(58, 13, 52, 250.00),(59, 13, 19, 300.00),(60, 9, 19, 0.00),(61, 17, 53, 150.00),(62, 7, 53, 450.00),(63, 22, 18, 120.00),(64, 7, 16, 450.00),(65, 7, 54, 450.00),(66, 7, 57, 450.00),(67, 17, 57, 150.00),(68, 7, 56, 450.00),(69, 17, 59, 150.00),(70, 7, 60, 450.00),(71, 17, 61, 150.00),(72, 17, 63, 150.00),(73, 21, 65, 25.00),(74, 7, 66, 450.00),(75, 7, 67, 450.00),(76, 11, 68, 385.00),(77, 7, 71, 450.00),(78, 11, 73, 385.00),(79, 13, 73, 300.00),(80, 4, 75, 200.00),(82, 7, 73, 30.00),(83, 18, 73, 127.50),(84, 23, 73, 120.00),(85, 7, 73, 30.00),(86, 10, 77, 382.50),(87, 7, 79, 550.00),(88, 17, 79, 150.00);
The given query was a possible edge case leading to no results in this example.
SELECT cart_id
FROM cart
INNER JOIN cartitem as c1 ON cart_id=c1.cartitem_cart_id AND c1.cartitem_package_id= 7
INNER JOIN cartitem as c3 ON cart_id=c3.cartitem_cart_id AND c3.cartitem_package_id= 9
INNER JOIN cartitem as c4 ON cart_id=c4.cartitem_cart_id AND c4.cartitem_package_id= 13
INNER JOIN cartitem as c5 ON cart_id=c5.cartitem_cart_id AND c5.cartitem_package_id= 17
INNER JOIN cartitem as c6 ON cart_id=c6.cartitem_cart_id AND c6.cartitem_package_id= 21
Output:
cart_id
-------------
19
19
The query should return all carts containing items that are connected to packages(7,9,13,17,21) in this case.
My approach to your problem would be:
SELECT
cart_id
FROM
cart
INNER JOIN
cartitem
ON
cart_id = cartitem_cart_id
WHERE
cartitem_package_id IN (7,9,13,17,21) -- items that got to be in the cart
GROUP BY
cart_id
HAVING
count(distinct cartitem_package_id) = 5 -- number of different packages
;
DEMO with your data
Explanation
The principle is to filter first with the list of the desired values, here your packages. Now count the different packages per cart (GROUP BY cart_id). If this count matches the number of values in your filter list, then every single package must be in this cart.
You can replace the value list of the IN clause with a subselect, if you get those values from a subselect.
You should see that this approach should be easy to adapt to similar needs.

Set auto_increment value to each unique group

I've got a MySQL innodb table (sqlfiddle demo) with
id, name_id, name, content
And content like
1, NULL, 'Brian', 'Bridge to terabithia'
2, NULL, 'Brian', 'Pulp fiction'
3, NULL, 'Brian', 'Trainspotting'
4, NULL, 'Luke', 'Watchmen'
5, NULL, 'Luke', 'Constantine'
6, NULL, 'Tony', 'Dark knight'
7, NULL, 'Tony', 'Shutter Island'
8, NULL, 'John', 'Machinist'
9, NULL, 'John', 'Matrix'
10, NULL, 'John', 'Sin city'
11, NULL, 'John', 'Mad Max'
The id is unique to each row. But I can't get, how to set auto_increment name_id to each unique name.
Here's (sqlfiddle) what I'm trying to achieve.
1, 1, 'Brian', 'Bridge to terabithia'
2, 1, 'Brian', 'Pulp fiction'
3, 1, 'Brian', 'Trainspotting'
4, 2, 'Luke', 'Watchmen'
5, 2, 'Luke', 'Constantine'
6, 3, 'Tony', 'Dark knight'
7, 3, 'Tony', 'Shutter Island'
8, 4, 'John', 'Machinist'
9, 4, 'John', 'Matrix'
10, 4, 'John', 'Sin city'
11, 4, 'John', 'Mad Max'
Is it possible to do with MySQL only?
Thank you for reading.
The short answer is you can't do this automatically with only auto_increment, and you probably shouldn't either.
If really have reason to do this you would be much better off normalizing your database, creating a "names" table (name_id PK, name) and removing the "name" column from this table. Honestly I'm not sure what you can really gain from doing this in your example, but I imagine it might be an abstraction of the problem.