Not sure how to loop in SQL over this data? - mysql

I'm trying to forumlate a query which will give me this result:
For each quiz number list the quiz number and the average high score. Only include the quizzes that more than 10 students took.
The query I am formulating looks like this:
SELECT QuizNum, AVG(HighScore) from quizzes WHERE NumStudents > 10;
This, however, gives me :
1, 20.75000
Which is incorrect data. I just really don't know where to start with this one.
The table looks like this:
'QuizNum', 'decimal(2,0)', 'NO', 'PRI', '0', ''
'QuizDate', 'date', 'NO', 'PRI', '0000-00-00', ''
'HighScore', 'decimal(3,1)', 'YES', '', '', ''
'LowScore', 'decimal(3,1)', 'YES', '', '', ''
'AvgScore', 'decimal(3,1)', 'YES', '', '', ''
'NumStudents', 'int(11)', 'YES', '', '', ''
'NumPassing', 'int(11)', 'YES', '', '', ''
So, foe example, every date quiz one occured has more than 10 students, so I need its average. Then I need the next quiz.
Table Contents:
1, '2009-01-25', 20.0, 9.0, 12.5, 15, 10
1, '2009-06-15', 30.0, 22.0, 25.6, ,
1, '2009-08-25', , , , 15, 10
1, '2010-01-24', 20.0, 9.0, 12.5, 17, 14
1, '2010-06-14', 28.5, 21.0, 26.6, 25, 25
1, '2010-08-24', , , , 21, 18
2, '2009-03-06', 18.0, 10.5, 15.0, 15, 12
2, '2009-07-01', 28.5, 18.5, 23.4, ,
2, '2009-09-21', 18.0, 10.5, 15.0, 15, 12
2, '2010-03-05', 18.5, 11.5, 15.2, 17, 14
2, '2010-06-30', 30.0, 25.0, 27.4, 23, 23
2, '2010-09-20', , , , 22, 19
3, '2009-03-24', 19.0, 14.5, 17.8, 13, 13
3, '2009-08-01', 27.5, 25.0, 16.2, ,
3, '2009-10-12', 19.0, 14.5, 17.8, 13, 13
3, '2010-03-23', 20.0, 17.0, 18.6, 16, 16
3, '2010-07-31', , , , 23, 20
3, '2010-10-11', 20.0, 9.0, 13.8, 22, 17
4, '2009-04-14', 20.0, 15.5, , ,
4, '2009-11-22', 20.0, 15.5, 17.9, ,
4, '2010-04-13', 20.0, 12.5, , ,
4, '2010-11-21', 20.0, 7.5, 13.9, 20, 15
5, '2009-05-04', 17.0, 8.5, 10.7, 10, 7
5, '2009-12-09', 17.0, 8.5, 10.7, 10, 7
5, '2010-04-03', 19.5, 11.5, 15.7, 15, 13
5, '2010-12-08', 20.0, 15.0, 17.3, 18, 18
Ideas?

For each quiz number
You need a GROUP BY:
SELECT QuizNum, AVG(HighScore)
FROM quizzes
WHERE NumStudents > 10
GROUP BY QuizNum;

You have to use GROUP BY clause like
SELECT QuizNum,
AVG(HighScore)
FROM quizzes
WHERE NumStudents > 10
GROUP BY QuizNum;

Related

Finding Connection Pairs

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

MySQL - How to find the rows with the greatest value changes?

I am trying to search a table where I have daily ranked keywords (SEO keywords). Therefore I have index on a key_id per keyword, and new position value per each keyword.
I would like to find out how I can select the keywords that have the greatest change in value?
MariaDB Table and data:
CREATE TABLE IF NOT EXISTS `daily_rank` (
`rankID` int(24) NOT NULL AUTO_INCREMENT,
`created` timestamp NULL DEFAULT current_timestamp(),
`key_id` int(100) NOT NULL DEFAULT 0,
`position` int(12) NOT NULL DEFAULT 0,
`keyword` varchar(50) NOT NULL DEFAULT '0',
PRIMARY KEY (`rankID`),
KEY `created` (`created`),
KEY `key_id` (`key_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3594 DEFAULT CHARSET=latin1;
INSERT INTO `daily_rank` (`rankID`, `created`, `key_id`, `position`, `keyword`) VALUES
(3594, '2019-10-09 17:59:07', 53, 4, 'SEO'),
(3595, '2019-10-09 17:59:07', 100, 3, 'agency'),
(3596, '2019-10-09 17:59:07', 397, 1, 'bureau marketing'),
(3597, '2019-10-09 17:59:07', 798, 7, 'marketing agency'),
(3598, '2019-10-09 17:59:07', 98, 8, 'search engine optimization'),
(3599, '2019-10-09 17:59:07', 346, 8, 'website optimization'),
(3600, '2019-10-09 17:59:07', 555, 9, 'agency'),
(3608, '2019-10-08 18:07:00', 53, 4, 'SEO'),
(3609, '2019-10-08 18:07:00', 100, 4, 'agency'),
(3610, '2019-10-08 18:07:00', 397, 3, 'bureau marketing'),
(3611, '2019-10-08 18:07:00', 798, 1, 'marketing agency'),
(3612, '2019-10-08 18:07:00', 98, 2, 'search engine optimization'),
(3613, '2019-10-08 18:07:00', 346, 2, 'website optimization'),
(3614, '2019-10-08 18:07:00', 555, 2, 'agency'),
(3615, '2019-10-07 18:07:22', 53, 4, 'SEO'),
(3616, '2019-10-07 18:07:22', 100, 6, 'agency'),
(3617, '2019-10-07 18:07:22', 397, 6, 'bureau marketing'),
(3618, '2019-10-07 18:07:22', 798, 6, 'marketing agency'),
(3619, '2019-10-07 18:07:22', 98, 4, 'search engine optimization'),
(3620, '2019-10-07 18:07:22', 346, 6, 'website optimization'),
(3621, '2019-10-07 18:07:22', 555, 6, 'agency'),
(3622, '2019-10-07 18:07:22', 53, 5, 'SEO'),
(3623, '2019-10-07 18:07:22', 100, 4, 'agency'),
(3624, '2019-10-07 18:07:22', 397, 5, 'bureau marketing'),
(3625, '2019-10-07 18:07:22', 798, 3, 'marketing agency'),
(3626, '2019-10-07 18:07:22', 98, 6, 'search engine optimization'),
(3627, '2019-10-07 18:07:22', 346, 3, 'website optimization'),
(3628, '2019-10-07 18:07:22', 555, 5, 'agency'),
(3629, '2019-10-06 18:07:44', 53, 1, 'SEO'),
(3630, '2019-10-06 18:07:44', 100, 2, 'agency'),
(3631, '2019-10-06 18:07:44', 397, 2, 'bureau marketing'),
(3632, '2019-10-06 18:07:44', 798, 1, 'marketing agency'),
(3633, '2019-10-06 18:07:44', 98, 1, 'search engine optimization'),
(3634, '2019-10-06 18:07:44', 346, 2, 'website optimization'),
(3635, '2019-10-06 18:07:44', 555, 2, 'agency'),
(3636, '2019-10-06 18:07:44', 53, 2, 'SEO'),
(3637, '2019-10-06 18:07:44', 100, 2, 'agency'),
(3638, '2019-10-06 18:07:44', 397, 3, 'bureau marketing'),
(3639, '2019-10-06 18:07:44', 798, 2, 'marketing agency'),
(3640, '2019-10-06 18:07:44', 98, 2, 'search engine optimization'),
(3641, '2019-10-06 18:07:44', 346, 1, 'website optimization'),
(3642, '2019-10-06 18:07:44', 555, 1, 'agency'),
(3643, '2019-10-06 18:07:44', 53, 1, 'SEO'),
(3644, '2019-10-06 18:07:44', 100, 2, 'agency'),
(3645, '2019-10-06 18:07:44', 397, 1, 'bureau marketing'),
(3646, '2019-10-06 18:07:44', 798, 3, 'marketing agency'),
(3647, '2019-10-06 18:07:44', 98, 2, 'search engine optimization'),
(3648, '2019-10-06 18:07:44', 346, 1, 'website optimization'),
(3649, '2019-10-06 18:07:44', 555, 3, 'agency'),
(3650, '2019-10-06 18:07:44', 53, 3, 'SEO'),
(3651, '2019-10-06 18:07:44', 100, 1, 'agency'),
(3652, '2019-10-06 18:07:44', 397, 2, 'bureau marketing'),
(3653, '2019-10-06 18:07:44', 798, 3, 'marketing agency'),
(3654, '2019-10-06 18:07:44', 98, 1, 'search engine optimization'),
(3655, '2019-10-06 18:07:44', 346, 2, 'website optimization'),
(3656, '2019-10-06 18:07:44', 555, 1, 'agency');
How do I query so I can get the latest position for the keywords, and the change from a given date, and order the result to show the keywords with the greatest change?
I imagine a table like this:
[Keyword] - [Todays Position] - [Position Change from yesterday]
where it is ordered by the biggest change descending
UPDATE:
When calculating max-min the todays position is within this calculation, and will skew the result somewhat.
And when viewing todays position, I would like to see the keywords that have had the biggest change in position since compared date.
I think this is what you want.
SELECT a.keyword, a.position as today_position, b.biggest_position_change_since_yesterday
FROM daily_rank a
JOIN
(SELECT keyword, MAX(position) - MIN(position) AS biggest_position_change_since_yesterday
FROM daily_rank
WHERE cast(created as date) >= ADDDATE(curdate(),-1)
GROUP BY keyword) b
ON b.keyword = a.keyword
AND cast(created as date) = curdate()
ORDER by biggest_position_change_since_yesterday desc;
keyword today_position biggest_position_change_since_yesterday
agency 9 7
agency 3 7
website optimization 8 6
marketing agency 7 6
search engine optimization 8 6
bureau marketing 1 2
SEO 4 0
Test Case:
DB<>FIDDLE
SELECT keyword, MAX(position) max_position,MIN(position) min_position FROM daily_rank GROUP BY keyword;
+----------------------------+--------------+--------------+
| keyword | max_position | min_position |
+----------------------------+--------------+--------------+
| agency | 9 | 1 |
| bureau marketing | 6 | 1 |
| marketing agency | 7 | 1 |
| search engine optimization | 8 | 1 |
| SEO | 5 | 1 |
| website optimization | 8 | 1 |
+----------------------------+--------------+--------------+

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.

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.

Select Parent node in nested data set

Have teh follwoing query which is fine and dandy...
SELECT
`node`.`site_pages_id` AS `page_id` ,
GROUP_CONCAT(`parent`.`site_pages_id` SEPARATOR '/') AS `path` ,
IFNULL( CONCAT( '/' , GROUP_CONCAT(`parent`.`url` SEPARATOR '/') ) , '/' ) AS `url`
FROM
`site_pages` AS `node`
LEFT JOIN
`site_pages` AS `parent`
ON
`node`.`lft_limit` BETWEEN `parent`.`lft_limit` AND `parent`.`rgt_limit`
GROUP BY
`node`.`site_pages_id`
ORDER BY
`node`.`lft_limit` ASC
produces the following
1, 1, /
2, 1/2, /about-us
8, 1/2/8, /about-us/meet-the-team
3, 1/3, /web
5, 1/5, /print
6, 1/6, /branding
7, 1/7, /contact-us
All sweet.
I'd like to select the immediate parent and just the immediate parent for each node.
My feeble attempts at doing so without a nasty subquery fail misearably (not much better with TBO).
Tips muchly appreciated
No probs Martin...
page_id url lft_limit rgt_limit
1, NULL, 1, 14,
2, about-us, 2, 5,
3, web, 6, 7,
5, print, 8, 9,
6, branding, 10, 11,
7, contact-us, 12, 13,
8, meet-the-team, 3, 4,