mysql select not does not work - mysql

I want to only select student IDs that do not have a row where product ID is 11. But I can't. What should I do?
BEGIN TRANSACTION;
CREATE TABLE STUDENTS(Id integer PRIMARY KEY, name text,year_born integer
);
CREATE TABLE PROJECT(project_id integer,title text,project_owner
text,year_written integer );
CREATE TABLE PROJECTWORKS(student_id integer,project_id integer);
INSERT INTO STUDENTS VALUES(1598,'james',1996);
INSERT INTO STUDENTS VALUES(2479,'andre',1996);
INSERT INTO STUDENTS VALUES(3682,'pierre',1997);
INSERT INTO PROJECT VALUES(10,'A','ABC',2008);
INSERT INTO PROJECT VALUES(11,'B','ABC',2010);
INSERT INTO PROJECT VALUES(12,'C','ABC',2016);
INSERT INTO PROJECT VALUES(13,'D','CBA',2014);
INSERT INTO PROJECTWORKS VALUES(1598,10);
INSERT INTO PROJECTWORKS VALUES(1598,11);
INSERT INTO PROJECTWORKS VALUES(1598,12);
INSERT INTO PROJECTWORKS VALUES(3682,12);
INSERT INTO PROJECTWORKS VALUES(3682,13);
INSERT INTO PROJECTWORKS VALUES(2479,12);
SELECT * FROM STUDENTS;
SELECT * FROM PROJECT;
SELECT * FROM PROJECTWORKS;
SELECT DISTINCT student_id FROM PROJECTWORKS
WHERE not project_id=11 and (project_id=10 OR project_id=12 OR
project_id=13);
I just want 3682 and 2479 Because 1598 has 11.

NOT EXISTS is perfect for this:
SELECT DISTINCT student_id
FROM PROJECTWORKS p
WHERE project_id IN (10, 12, 13)
AND NOT EXISTS
(SELECT 1
FROM PROJECTWORKS p2
WHERE p.student_id = p2.student_id
AND p2.project_id = 11);
Also, I assume you meant you don't want ID 11, as I didn't see 14 in your example.

If I understood you right, this is what you want
SELECT DISTINCT student_id FROM PROJECTWORKS
WHERE student_id not in
(select student_id from PROJECTWORKS where project_id=11)

You could use a join between the two result
select distinct student_id
from PROJECTWORKS p
where project_id NOT IN (11)
INNER JOIN (
Select distinct student_id
from PROJECTWORKS
where project_id IN ( 10, 12, 13)
) T on t.student_id = p.student_id

SELECT DISTINCT student_id FROM PROJECTWORKS
WHERE student_id not in
(select student_id from PROJECTWORKS where project_id=11)
Your question is not clear. above code snippet is for distinct student_id which does not have project_id as 11

Related

In MySql, How to Associate Three Random Rows from One Table to Each Row of a Another Table

I have a table of Friends (Ann, Bob, Carl) and a table of Fruits (Apple, Banana, Cherry, Date, Fig, Grapefruit)
I need to create an intersection table (Friends X Fruit) that associates each Friend with 3 randomly selected fruits.
For example:
Ann might be associated with Cherry, Date, Fig
Bob might be associated with Apple, Fig, Banana
Carl might be associated with Banana, Cherry, Date
I have developed a script that works well for only ONE friend (pasted below), but I am struggling to expand the script to handle all of the friends at once.
(If I remove the WHERE clause, then every friend gets assigned the same set of fruits, which doesn't meet my requirement).
Setup statements and current script pasted below.
Thank you for any guidance!
CREATE TABLE TempFriends ( FirstName VARCHAR(24) );
CREATE TABLE TempFruits ( FruitName VARCHAR(24) );
CREATE TABLE FriendsAndFruits( FirstName VARCHAR(24), FruitName VARCHAR(24) );
INSERT INTO TempFriends VALUES ('Ann'), ('Bob'), ('Carl');
INSERT INTO TempFruits VALUES ('Apple'), ('Banana'), ('Cherry'), ('Date'), ('Fig'), ('Grapefruit');
INSERT INTO FriendsAndFruits( FirstName, FruitName )
SELECT FirstName, FruitName
FROM TempFriends
INNER JOIN ( SELECT FruitName FROM TempFruits ORDER BY RAND() LIMIT 3 ) RandomFruit
WHERE FirstName = 'Bob';
INSERT INTO FriendsAndFruits
SELECT FirstName,
FruitName
FROM (
SELECT FirstName,
FruitName,
ROW_NUMBER() OVER (PARTITION BY FirstName ORDER BY RAND()) rn
FROM TempFriends
CROSS JOIN TempFruits
) subquery
WHERE rn <= 3;
INSERT INTO FriendsAndFruits( FirstName, FruitName )
SELECT FirstName, FruitName
FROM TempFriends
JOIN LATERAL (
SELECT FruitName
FROM TempFruits
ORDER BY TempFriends.FirstName, RAND() LIMIT 3
) RandomFruit;
INSERT INTO FriendsAndFruits( FirstName, FruitName )
SELECT FirstName, FruitName
FROM TempFriends
JOIN LATERAL (
SELECT TempFriends.FirstName tmp, FruitName
FROM TempFruits
ORDER BY RAND() LIMIT 3
) RandomFruit;
fiddle

SELECT SUM(FieldName) FROM TableName between Column_Value and Column_Value;

Everyone. I have SQL Query Questions.
can I calculate the values between two columns.?
for. example. I have a table Book;
CREATE TABLE Book(
ID int,
DateOfSellBook Date,
Book varchar(255),
SellBook int (255),
);
INSERT INTO `book`(`ID`, `Date`, `Book Title`, `Sell Book`) VALUES (1, 3/2/2021, Java,10);
INSERT INTO `book`(`ID`, `Date`, `Book Title`, `Sell Book`) VALUES (2,3/3/2021,Java,10);
INSERT INTO `book`(`ID`, `Date`, `Book Title`, `Sell Book`) VALUES (3,3/4/2021,javascript,10);
INSERT INTO `book`(`ID`, `Date`, `Book Title`, `Sell Book`) VALUES (4,3/5/2021,php,10);
between ID 1 and 3, How Many Books Sell ?.
SELECT SUM(FieldName) FROM TableName between Column_Value and Column_Value; but it's not working for me please help
Try this:
SELECT count(distinct book_number) FROM book
where id between 1 and 4
This query will give you list of unique book_number between id 1 and 4. To get all the book_number (if there is a book named 'book a' two times then it will be counted two times):
SELECT count(book_number) FROM book
where id between 1 and 4

mysql max per group by date

I have two mysql greatest-n-per-group, greatest-by-date problems:
Considering one students table and one grades table, I want to have all students displayed with their most recent grade.
The schema script:
CREATE TABLE student (
id int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO student VALUES(1, 'jim');
INSERT INTO student VALUES(2, 'mark ');
INSERT INTO student VALUES(3, 'john');
CREATE TABLE grades (
id int(11) NOT NULL AUTO_INCREMENT,
student_id int(11) NOT NULL,
grade int(11) NOT NULL,
`date` date DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO grades VALUES(1, 1, 6, NULL);
INSERT INTO grades VALUES(2, 1, 8, NULL);
INSERT INTO grades VALUES(3, 1, 10, NULL);
INSERT INTO grades VALUES(4, 2, 9, '2016-05-10');
INSERT INTO grades VALUES(5, 2, 8, NULL);
INSERT INTO grades VALUES(6, 3, 6, '2016-05-26');
INSERT INTO grades VALUES(7, 3, 7, '2016-05-27');
A) I want to find out if this is a valid solution for getting the most recent record by a date field (date) from a secondary table (grades) grouped for each row in a main table (student).
My query is:
SELECT s.id, s.name, g.grade, g.date
FROM student AS s
LEFT JOIN (
SELECT student_id, grade, DATE
FROM grades AS gr
WHERE DATE = (
SELECT MAX(DATE)
FROM grades
WHERE student_id = gr.student_id
)
GROUP BY student_id
) AS g ON s.id = g.student_id
Sql Fiddle: http://sqlfiddle.com/#!9/a84171/2
This query displays the desired (almost) results. But I have doubts that this is the best approach because it looks ugly, so I am very curious about the alternatives.
B) The second problem is the reason for the (almost) above,
For the first row, name=Jim it finds no grade though we have grades for Jim.
So just in case the query above would be valid only for NOT NULL date fields.
The question would be:
How to get the most recent grade for all the students who have grades, including Jim even that his grades has no date specified (NULL). In this case the most recent grouping will be given by the latest row inserted (MAX(id)) or just random.
Doesn't work with replacing date = (SELECT... with date IN (SELECT ....
Any help would be much appreciated,
Thanks!
[UPDATE #1]:
For B) I found adding this to the sub-query, OR date IS NULL, produces the desired result:
SELECT s.id, s.name, g.grade, g.date
FROM student AS s
LEFT JOIN (
SELECT id, student_id, grade, DATE
FROM grades AS gr
WHERE DATE = (
SELECT MAX(DATE)
FROM grades
WHERE student_id = gr.student_id
) OR date IS NULL
GROUP BY student_id
) AS g ON s.id = g.student_id
[UPDATE #2]
Seems the previous update worked if the first grade has a date for a student. It doesn't if the first grade is null. I would have linked a fiddle but it seems sqlfiddle doesn't work now.
So this is what I came up until now that seems to solve the B) problem:
SELECT s.id, s.name, g.grade, g.date
FROM student AS s
LEFT JOIN (
SELECT id, student_id, grade, DATE
FROM grades AS gr
WHERE (
`date` = (
SELECT MAX(DATE)
FROM grades
WHERE student_id = gr.student_id
)
) OR (
(
SELECT MAX(DATE)
FROM grades
WHERE student_id = gr.student_id
) IS NULL AND
date IS NULL
)
) AS g ON s.id = g.student_id
GROUP BY student_id
I still would like to know if you guys know better alternatives to this ugly thing.
Thanks!
[UPDATE #3]
#Strawberry
The desired results would be:
id name grade date
1 jim 10 NULL
2 mark 9 2016-05-10
3 john 7 2016-05-27
each student with one corresponding grade
if a date exists for a grade, then get the most recent one.
The complexity of this problem stems from the logical impossibility of a grade without an associated date, so obviously the solution is to fix that.
But here's a workaround...
E.g.:
SELECT a.*
FROM grades a
JOIN
( SELECT student_id
, MAX(COALESCE(UNIX_TIMESTAMP(date),id)) date
FROM grades
GROUP
BY student_id
) b
ON b.student_id = a.student_id
AND b.date = COALESCE(UNIX_TIMESTAMP(a.date),id);
http://sqlfiddle.com/#!9/ecec43/4
SELECT s.id, s.name, g.grade, g.date
FROM student AS s
LEFT JOIN (
SELECT gr.student_id, gr.grade, gr.DATE
FROM grades AS gr
LEFT JOIN grades grm
ON grm.student_id = gr.student_id
AND grm.date>gr.date
WHERE grm.student_id IS NULL
AND gr.date IS NOT NULL
GROUP BY gr.student_id
) AS g
ON s.id = g.student_id;

Equations in SQL (MySQL)

I have a table with a cost_maintence column that has cost for the entire year(52) weeks. I also have a table of renters, and a table of renter_units where there is a week_owned column that has the week number the renter rented. I am trying to figure out how I could calculate the cost for each renter. The equation I came up with is:
what each person owes = (cost_maintence/52) * #weeks each renter
rented
Is there any way I could get the value from a query?
create table renters(
id,
lname,
fname,
phone_num);
create table unit(
id,
unit_name,
unit_num,
cost_maintence);
create table renters_unit(
renters_id,
unit_id,
week_owned);
This is the query I came up with but I have no way of testing it out
select r.lname, r.fname, count(ru.week_owned),
sum(u.cost_maintence/52*count(ru.week_owned))
from renters r, renters_units ru, units u
where r.id = ru.renter_id
and ru.unit_id = u.id
and u.unit_name =unitname
and u.unit_num = unitnum
group by lname
order by lname,fname asc;
Here's an example. The inner query will get you amount owed per item, and the outer query sums that to find the total owed per person.
SELECT fname, SUM(owes) AS total_due
FROM (
SELECT r.fname,
r.id,
u.unit_name,
u.cost_maintence/52*COUNT(ru.week_owned) AS owes
FROM renters AS r
INNER JOIN renters_unit AS ru ON r.id = ru.renters_id
INNER JOIN unit AS u ON u.id = ru.unit_id
GROUP BY r.id, u.id
) AS t
GROUP BY id
Try it out with a SQLFiddle demo
Example Schema:
create table renters(
id int,
lname varchar(20),
fname varchar(20),
phone_num varchar(20));
create table unit(
id int,
unit_name varchar(30),
unit_num int,
cost_maintence int);
create table renters_unit(
renters_id int,
unit_id int,
week_owned int);
INSERT INTO renters VALUES (1, 'Peterson', 'Chaz', '8675309');
INSERT INTO unit VALUES (1, 'Skateboard', 1337, 52);
INSERT INTO unit VALUES (2, 'Flamethrower', 5432, 104);
INSERT INTO renters_unit VALUES (1, 1, 1);
INSERT INTO renters_unit VALUES (1, 1, 2);
INSERT INTO renters_unit VALUES (1, 1, 4);
INSERT INTO renters_unit VALUES (1, 2, 4);
INSERT INTO renters_unit VALUES (1, 2, 5);
By this, we can see that Chaz should owe $7 for the year (had a skateboard for 3 weeks at $1 per week, and a flamethrower for 2 weeks at $2 per week).
The inner query gives the following:
FNAME UNIT_NAME OWES
Chaz Skateboard 3
Chaz Flamethrower 4
And the outer:
FNAME TOTAL_DUE
Chaz 7
SELECT t.renters_id, SUM(u.cost_maintence)/52
FROM unit u JOIN renters_unit t ON t.unit_id = u.id
GROUP BY t.renters_id

query to find diff between two records

I have following tables
movies
- id
details
- user_id
- movie_id
- rating
users
- id
detail belongs to user and movie
I want to find the the diff between the rating of two users say id 3,10
simply I want answer of this
sum(10-(user1.rating - user2.rating))
where rating is > 0
i.e both users should have given at-least non zero rating
select
d1.movie_id
, d1.rating as user1Rating
, d2.rating as user2Rating
, abs(d1.rating - d2.rating)
from
details d1
inner join details d2 on d1.movie_id = d2.movie_id
where d1.user_id = 1
and d2.user_id = 2
See it working live in an sqlfiddle.
CREATE TABLE ratings
( userId int, movieId int, rating int)
INSERT INTO ratings (userId, movieId, rating) VALUES
(3, 1, 5), (10, 1, 8),
(3, 2, 10), (10, 2, 3)
SELECT r1.movieId, (r1.rating - r2.rating) FROM ratings as r1
INNER JOIN ratings as r2 on r1.movieId = r2.movieId
WHERE r1.userId = 3 and r2.userId = 10
DECLARE #UserRating1 int
DECLARE #UserRating2 int
DECLARE #UserID1 int
DECLARE #UserID2 int
DECLARE #MovieID int
SET #MovieID = 99
SET #UserID1 = 3
SET #UserID2 = 10
SET #UserRating1 = (SELECT Rating FROM details WHERE movie_id = #MovieID AND user_id = #UserID1 AND Rating > 0)
SET #UserRating2 = (SELECT Rating FROM details WHERE movie_id = #MovieID AND user_id = #UserID2 AND Rating > 0)
PRINT #UserRating1 - #UserRating2
Update: I replace the syntax from MSSQL to MySql
You can check this on SQL Fiddle:
create table movies (id int);
insert into movies (id) values (1);
insert into movies (id) values (2);
insert into movies (id) values (3);
insert into movies (id) values (4);
insert into movies (id) values (5);
create table users (id int);
insert into users (id) values (1);
insert into users (id) values (2);
insert into users (id) values (3);
insert into users (id) values (4);
insert into users (id) values (5);
insert into users (id) values (10);
create table details (user_id int, movie_id int, rating int);
insert into details (user_id, movie_id, rating) values (3,1,1);
insert into details (user_id, movie_id, rating) values (3,2,2);
insert into details (user_id, movie_id, rating) values (3,3,3);
insert into details (user_id, movie_id, rating) values (3,4,1);
insert into details (user_id, movie_id, rating) values (3,5,4);
insert into details (user_id, movie_id, rating) values (10,1,3);
insert into details (user_id, movie_id, rating) values (10,2,1);
insert into details (user_id, movie_id, rating) values (10,3,2);
insert into details (user_id, movie_id, rating) values (10,4,1);
insert into details (user_id, movie_id, rating) values (10,5,5);
and
select
sum(10-(details1.rating - details2.rating))
from
movies
inner join details details1 on movies.id = details1.movie_id
inner join users user1 on details1.user_id = user1.id
inner join details details2 on movies.id = details2.movie_id
inner join users user2 on details2.user_id = user2.id
where
(user1.id=3)
and
(user2.id=10)
and
(details1.rating is not null) and (details1.rating > 0)
and
(details2.rating is not null) and (details2.rating > 0)