Counting number of files in a folder in mysql - mysql

I have these tables
Create table series (
id_series Int NOT NULL AUTO_INCREMENT,
name_series Varchar(100) NOT NULL,
kcal Int NOT NULL DEFAULT 0,
type Varchar(20) NOT NULL,
id_user Int NOT NULL,
UNIQUE (name_excercise),
Primary Key (id_series)) ENGINE = MyISAM;
Create table excercise (
id_excercise Int NOT NULL AUTO_INCREMENT,
name_excercise Char(100) NOT NULL,
date Date NOT NULL,
start Time NOT NULL,
end Time NOT NULL,
km Double(10,2) NOT NULL,
id_series Int NOT NULL,
UNIQUE (id_excercise),
Primary Key (id_excercise)) ENGINE = MyISAM;
They are basically like folders. Series has a name of a series and inside, there are subsequent excercises. What I need is to return every series user has and the number of the excercises inside. But I am having trouble with it, since I am not passing any ID of a concrete series in which it could count all the excercises. Is it possible to print that with only a user id?
I basically have this:
"SELECT * FROM series WHERE id_user = $id_user"
but need to combine it with this:
"SELECT COUNT(*) FROM excercise WHERE id_series = $id_series"
without the need of id_series.

This is the query:
SELECT S.*, COUNT(E.id_excercise) AS NumOfExc
FROM series AS S
JOIN excercise AS E
ON S.id_series = E.id_series
WHERE S.id_user = '$id_user'
GROUP BY E.id_series
UNION
SELECT *, 0 AS NumOfExc
FROM series
WHERE id_user = '$id_user'
AND id_series NOT IN (
SELECT S.id_series AS id_series
FROM series AS S
JOIN excercise AS E
ON S.id_series = E.id_series
WHERE S.id_user = '$id_user'
GROUP BY E.id_series
)
The above query will show what you need.

Related

MySQL max and count aggregate functions

So I have three tables
CREATE TABLE Personnel(
IdPersonnel INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
Name VARCHAR(45) NOT NULL,
Surename VARCHAR(45) NOT NULL,
Department VARCHAR(45) NOT NULL,
Salary INT NOT NULL,
Birthday DATE NOT NULL
);
CREATE TABLE Doctor(
IdDoctor INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
fk_Personnel INT NOT NULL
);
CREATE TABLE Visit(
IdVisit INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
Date DATE NOT NULL,
ControlDate DATE,
fk_Patient INT NOT NULL,
fk_Doctor INT NOT NULL,
);
From these three tables, I need to get a doctor who had most of the visits.
SELECT p.Name, p.Surname, COUNT(*) visits
FROM Visit v
JOIN Doctor d
ON v.fk_Doctor = d.IdDoctor
JOIN Personnel p
ON d.fk_Personnel = p.IdPersonnel
GROUP BY d.IdDoctor
ORDER BY COUNT(*) DESC
LIMIT 1;
I used this query, and the result is correct, but I have to use MAX() function. I am using MySQL Community server 8.0.26
select P.Name, P.Surename, P.IdPersonnel ,count(*) from Visit V
inner join Doctor D on V.fk_Doctor = D.IdDoctor
inner join Personnel P on D.fk_Personnel = P.IdPersonnel
group by P.Name, P.Surename, P.IdPersonnel
having count(*) = (
select max(visits) from
(select fk_Doctor, count(*) visits from Visit group by fk_Doctor) a
)

How to display multiple items but only the highest values in year and month for each?

I have the following two tables:
CREATE DATABASE IF NOT EXISTS springbootdb;
DROP TABLE IF EXISTS occupancy;
DROP TABLE IF EXISTS hotel;
CREATE TABLE hotel
(
id INT NOT NULL PRIMARY KEY auto_increment,
category int NOT NULL,
name TEXT NOT NULL,
owner TEXT NOT NULL,
contact TEXT NOT NULL,
address TEXT NOT NULL,
city TEXT NOT NULL,
zip TEXT NOT NULL,
phone TEXT NOT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE occupancy
(
id int not null primary key auto_increment,
hotelid int not null,
month int not null,
year int not null,
room_utilization int not null,
bed_utilization int not null,
room_count int not null,
bed_count int not null,
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Now I want to display every single hotel.id and hotel.name along with occupancy.room_count, occupancy.bed_count, occupancy.room_utilization and occupancy.bed_utilization - but only the very latest entry for each hotel.id, so the ones where occupancy.year and occupancy.month are the highest values each.
I tried a couple of things, such as
SELECT springbootdb.hotel.id, springbootdb.hotel.name, springbootdb.occupancy.bed_count, springbootdb.occupancy.bed_utilization
From springbootdb.hotel
INNER JOIN springbootdb.occupancy
ON hotel.id = occupancy.hotelid
order by springbootdb.occupancy.`year`, springbootdb.occupancy.`month` asc limit 1;
but haven't had any success unfortunately.
Can a good soul tell me how to get there?
Thanks!
This is best solved with window functions, but that requires you upgrade to MySQL 8.0.
Here's the general idea.
SELECT t.id, t.name, t.bed_count, t.bed_utilization
FROM (
SELECT h.id, h.name, o.bed_count, o.bed_utilization, ROW_NUMBER() OVER (PARTITION BY h.id ORDER BY o.`year` DESC, o.`month` DESC) AS rownum
FROM hotel AS h JOIN occupacy AS o ON h.id = o.hotelid
) AS t
WHERE t.rownum = 1;

MySQL Query to get all neighborhoods which a user did not join

I want to get all the neighborhoods (based on different zips) which the user is not a member of already.
I have a users table and several other tables like this:
table name: neighborhood
CREATE TABLE neighborhood(
`neighborhood_id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL,
`description` TEXT DEFAULT NULL,
`neighborhood_postal_code` VARCHAR(255) NOT NULL,
`region_neighborhood` VARCHAR(255) NOT NULL,
`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`neighborhood_id`),
INDEX `neighborhood_region_neighborhood_FI_1` (`region_neighborhood`)
) ENGINE = InnoDB;
table name: user_neighborhood
CREATE TABLE user_neighborhood(
`user_id` INT(11) NOT NULL,
`neighborhood_id` INT(11) NOT NULL,
`activity_circle` INT(1) DEFAULT 0,
`duo_circle` INT(1) DEFAULT 0,
FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`),
FOREIGN KEY (`neighborhood_id`) REFERENCES `neighborhood` (`neighborhood_id`)
) ENGINE = InnoDB;
I have tried the following query, but the result is not correct:
SELECT n.*
FROM `neighborhood` as n
left join user_neighborhood as un on n.neighborhood_id = un.neighborhood_id
where un.user_id != 1 and n.neighborhood_postal_code IN ('2000', '2100')
UPDATE: I managed to make the query seem correct at first instance using a subquery like this:
select *
from neighborhood
where neighborhood_id NOT IN (select neighborhood_id from user_neighborhood where user_id != 1)
AND neighborhood_postal_code IN ('2000', '2100')
However, it also returns (some) of the neighborhoods i am in already. It doesnot make much sense to me why only some..
Why exactly are you adding user_id != 1 in your subquery? I think if you know the id of the user you want to fetch for lets say user_id is 10 then use where user_id = 10 in subquery like:
select *
from neighborhood
where neighborhood_id NOT IN (select distinct neighborhood_id from user_neighborhood where user_id = 10)
AND neighborhood_postal_code IN ('2000', '2100')
But if you want to fetch all the neighbors which have no user then you can use this Query:
select *
from neighborhood
where neighborhood_id NOT IN (select distinct neighborhood_id from user_neighborhood)
AND neighborhood_postal_code IN ('2000', '2100')
Hope this helps!

Select only the last inserted item related to another registry

I modeled a small database for easier explanation:
CREATE TABLE bands (
id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(120) NULL,
PRIMARY KEY(id)
)
TYPE=InnoDB;
CREATE TABLE albums (
id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
band_id INTEGER UNSIGNED NOT NULL,
album_name VARCHAR(120) NULL,
rating INTEGER UNSIGNED NULL,
insertion_date TIMESTAMP NULL,
PRIMARY KEY(id),
INDEX albums_FKIndex1(band_id),
FOREIGN KEY(band_id)
REFERENCES bands(id)
ON DELETE NO ACTION
ON UPDATE NO ACTION
)
TYPE=InnoDB;
Now, pretending that we already have some bands and many albums registered in their respective tables, I want to select ONLY the last inserted album from each registered band.
PS: I have to use the "album.insertion_date" field to determine which album is the last inserted.
Try joining the two tables and filtering by insertion_date and band:
SELECT al.*
FROM albums al
INNER JOIN bands b ON al.band_id=b.id
WHERE al.insertion_date=(
SELECT max(insertion_date)
FROM albums
WHERE band_id=b.id
)
Try this one:
select b.name, a.album_name, a.isertion_date
from bands b, albums a
where a.band_id = b.id
and a.insertion_date = (select max(a1.insertion_date) from albums a1 where a1.band_id = b.id)
Considering that you have the albums' ids to be AUTO_INCREMENT and the possibility for the insertion_date to be NULL(as it is the default value), using insertion_date to determine the results is not the smartest thing to do but ... there you go:
SELECT DISTINCT band, last_album, insertion_date
FROM (
SELECT bands.name AS band, albums.album_name AS last_album, albums.insertion_date
FROM bands
JOIN albums ON bands.id=albums.band_id
ORDER BY albums.insertion_date DESC
) t1
GROUP BY band;

MySQL aggregation problems

I'm trying to count how many essays have been graded so I know how many results to display on the page. But I can't seem to get the code to work properly can someone help?
Thanks for the help in advance!
Here is what I got so far.
SELECT students.*, students_essays.*, COUNT(students_essays.id)
FROM students
INNER JOIN students_essays ON students.student_id = students_essays.student_id
INNER JOIN essays_grades ON students_essays.id = essays_grades.students_essays_id
It should look something like the code below for my pagination.
$q = "SELECT COUNT(id) FROM students_essays";
$r = mysqli_query ($mysqli, $q) or trigger_error("Query: $q\n<br />MySQL Error: " . mysqli_error($mysqli));
$row = mysqli_fetch_array ($r);
$records = $row[0];
Just in case here is my MySQL tables.
CREATE TABLE students_essays (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
student_id INT UNSIGNED NOT NULL,
content TEXT NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE students (
student_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
student_first_name VARCHAR(255) DEFAULT NULL,
student_last_name VARCHAR(255) DEFAULT NULL,
pass CHAR(40) NOT NULL,
PRIMARY KEY (student_id)
);
CREATE TABLE essays_grades (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
grade_id INT UNSIGNED NOT NULL,
students_essays_id INT UNSIGNED NOT NULL,
student_id INT UNSIGNED NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE grades (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
letter_grade VARCHAR(2) DEFAULT NULL,
grade_points FLOAT UNSIGNED NOT NULL DEFAULT 0,
PRIMARY KEY (id)
);
Here is the error message.
Error: 1140 - Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause in
Well I am guessing here based on the information at hand...
$q = "SELECT COUNT(id) FROM students_essays se INNER JOIN essays_grades eg ON se.id = eg.students_essays_id";
That would return all essays with a matching grade record.
SELECT students.*, students_essays.*, COUNT(students_essays.id)...
students.* and students_essays.* return multiple rows but COUNT(students_essays.id) would always return just one row. In my experience, MySQL returns the number of rows and the very first row only. The simplest way to do what you want might be running two separate queries: one for count and the other for fetching actual data.