Two joins change case size - sql

My question is why double joins in SQLite change case size in result.
Please look in fiddle:
http://sqlfiddle.com/#!7/88671/3
As you can see when I query "select * from user" I have upper size name A123456, but when I do double join I have only lower size name a123456.
Can someone explain why?
Schema below:
CREATE TABLE user (id integer primary key, n_login varchar(64), name varchar(128), CONSTRAINT a UNIQUE (n_login, name) ON CONFLICT IGNORE);
CREATE TABLE role (id integer primary key, name text unique, description text);
CREATE TABLE user_to_role (user_id integer REFERENCES user(id), role_id integer REFERENCES role(id), PRIMARY KEY (user_id, role_id));
CREATE TABLE role_to_database (id integer, role_id integer REFERENCES role(id), database_id integer REFERENCES databases(id), PRIMARY KEY (role_id, database_id));
insert into user (n_login, name) values ("a123456", "A123456");
insert into user (n_login, name) values ("a123456", "a123456");
insert into user (n_login, name) values ("a000000", "A000000");
insert into user_to_role (user_id, role_id) values (2, 1);
insert into user_to_role (user_id, role_id) values (2, 2);
insert into user_to_role (user_id, role_id) values (3, 3);
insert into role_to_database (role_id, database_id) values (1, 3);
insert into role_to_database (role_id, database_id) values (2, 8);
insert into role_to_database (role_id, database_id) values (3, 1);
With this query I have A123456:
select * from user;
With this query I have also A123456:
select * from role_to_database inner join user_to_role ON role_to_database.role_id = user_to_role.role_id inner join user;
But with this query I only have a123456:
select * from role_to_database inner join user_to_role ON role_to_database.role_id = user_to_role.role_id inner join user ON user.id = user_to_role.user_id;

The query returns exactly the data inserted:
insert into user_to_role (user_id, role_id) values (2, 1);
insert into user_to_role (user_id, role_id) values (2, 2);
insert into user_to_role (user_id, role_id) values (3, 3);
as user_id=1 takes no role.
Did you mean
insert into user_to_role (user_id, role_id) values (1, 1); -- 1
insert into user_to_role (user_id, role_id) values (2, 2);
insert into user_to_role (user_id, role_id) values (3, 3);
? Then you'll get 'A123456' too.

its a random process without using order by. so to get data in order you have to use order by in your query
select * from user order by name

Related

How can I fix the error in duplicate tuples and sort correctly?

Can anyone help me understand the error?
My query:
select s1.name, s1.grade, s2.name, s2.grade
from student s1, student s2, likes l1, likes l2
where (s1.id_student = l1.id_student1 and s2.id_student = l1.id_student2)
and (s2.id_student = l2.id_student1 and s1.id_student = l2.id_student2)
and s1.name <= s2.name
order by s1.name, s2.name;
Return:
Cassandra|9 Gabriel|9
Gabriel 11|Gabriel|9
Gabriel|9|Gabriel|11
Jessica 11|Kyle|12
But the correct thing would be [exactly in that order]:
Cassandra|9|Gabriel|9
Jessica|11|Kyle|12
Gabriel|9|Gabriel|11
RS3 - For every pair of students who both like each other, return the name and grade of both students. Include each pair only once, with the two names in alphabetical order.
CREATE SCHEMA socialnetworkschema;
/* Create the schema for our tables */
SET SEARCH_PATH=socialnetworkschema;
CREATE TABLE socialnetworkschema.student (
id_student SERIAL PRIMARY KEY,
name varchar(255) DEFAULT NULL,
grade int DEFAULT NULL
);
CREATE TABLE socialnetworkschema.friend (
id_student1 int DEFAULT NULL,
id_student2 int DEFAULT NULL,
FOREIGN KEY (id_student1) REFERENCES socialnetworkschema.student (id_student) ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY (id_student2) REFERENCES socialnetworkschema.student (id_student) ON DELETE CASCADE ON UPDATE CASCADE
);
CREATE TABLE socialnetworkschema.likes (
id_student1 int DEFAULT NULL,
id_student2 int DEFAULT NULL,
FOREIGN KEY (id_student1) REFERENCES socialnetworkschema.student (id_student) ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY (id_student2) REFERENCES socialnetworkschema.student (id_student) ON DELETE CASCADE ON UPDATE CASCADE
);
/* Populate the tables with our data */
insert into socialnetworkschema.student values (1689, 'Gabriel', 9);
insert into socialnetworkschema.student values (1510, 'Jordan', 9);
insert into socialnetworkschema.student values (1381, 'Tiffany', 9);
insert into socialnetworkschema.student values (1709, 'Cassandra', 9);
insert into socialnetworkschema.student values (1101, 'Haley', 10);
insert into socialnetworkschema.student values (1782, 'Andrew', 10);
insert into socialnetworkschema.student values (1468, 'Kris', 10);
insert into socialnetworkschema.student values (1641, 'Brittany', 10);
insert into socialnetworkschema.student values (1247, 'Alexis', 11);
insert into socialnetworkschema.student values (1316, 'Austin', 11);
insert into socialnetworkschema.student values (1911, 'Gabriel', 11);
insert into socialnetworkschema.student values (1501, 'Jessica', 11);
insert into socialnetworkschema.student values (1304, 'Jordan', 12);
insert into socialnetworkschema.student values (1025, 'John', 12);
insert into socialnetworkschema.student values (1934, 'Kyle', 12);
insert into socialnetworkschema.student values (1661, 'Logan', 12);
insert into socialnetworkschema.friend values (1510, 1381);
insert into socialnetworkschema.friend values (1510, 1689);
insert into socialnetworkschema.friend values (1689, 1709);
insert into socialnetworkschema.friend values (1381, 1247);
insert into socialnetworkschema.friend values (1709, 1247);
insert into socialnetworkschema.friend values (1689, 1782);
insert into socialnetworkschema.friend values (1782, 1468);
insert into socialnetworkschema.friend values (1782, 1316);
insert into socialnetworkschema.friend values (1782, 1304);
insert into socialnetworkschema.friend values (1468, 1101);
insert into socialnetworkschema.friend values (1468, 1641);
insert into socialnetworkschema.friend values (1101, 1641);
insert into socialnetworkschema.friend values (1247, 1911);
insert into socialnetworkschema.friend values (1247, 1501);
insert into socialnetworkschema.friend values (1911, 1501);
insert into socialnetworkschema.friend values (1501, 1934);
insert into socialnetworkschema.friend values (1316, 1934);
insert into socialnetworkschema.friend values (1934, 1304);
insert into socialnetworkschema.friend values (1304, 1661);
insert into socialnetworkschema.friend values (1661, 1025);
insert into socialnetworkschema.friend select id_student2, id_student1 from friend;
insert into socialnetworkschema.likes values(1689, 1709);
insert into socialnetworkschema.likes values(1709, 1689);
insert into socialnetworkschema.likes values(1782, 1709);
insert into socialnetworkschema.likes values(1911, 1247);
insert into socialnetworkschema.likes values(1247, 1468);
insert into socialnetworkschema.likes values(1641, 1468);
insert into socialnetworkschema.likes values(1316, 1304);
insert into socialnetworkschema.likes values(1501, 1934);
insert into socialnetworkschema.likes values(1934, 1501);
insert into socialnetworkschema.likes values(1025, 1101);
insert into socialnetworkschema.likes values(1689, 1911);
insert into socialnetworkschema.likes values(1911, 1689);
First of all, you should consider rewriting your query to use explicit modern joins. After this, your logic for connecting two student records needs to change a bit.
with cte as (
select
s1.name as name1, s1.grade as grade1, s2.name as name2, s2.grade as grade2,
row_number() over (partition by least(s1.name, s2.name), greatest(s1.name, s2.name) order by s1.name) rn
from student s1
inner join likes l1
on s1.id_student = l1.id_student1
inner join student s2
on l1.id_student2 = s2.id_student
inner join likes l2
on l2.id_student1 = s2.id_student and
l2.id_student2 = s1.id_student
where s1.id_student <> s2.id_student
order by s1.name, s2.name
)
select name1, grade1, name2, grade2
from cte
where rn = 1;
Demo
Since your requirement is to find all students who mutually liked each other, we approach this by making a round trip to and from the student table. The likes table is what is known as a junction table in SQL. It exists to represent a one directional liked from one student to another. We join as follows:
student -> likes -> student -> likes ---
^ |
|___________________________________|
That is, a mutual like means that there exists a path we can find matching the above cycle.

One time each one

I have build my database ofcourse etc but I have problem with the code.I try to solve that
"Names of marines(one time each one) that have for reservation red boat and their have tonnage bigger than 200." and I did that.
Select distinct m.name
From marina m join reservation r on (m.mid, r.mid)
Where r.bid = (select b.bid from boat b where b.color = "red")
I tryed use that https://senseful.github.io/text-table/ but I failed so I post here if someone can help edited.That is my database.
drop table if exists reservation;
drop table if exists marina;
drop table if exists boat;
drop table if exists sailor;
create table boat
(bid integer not null constraint c_bid primary key,
bname varchar(40),
color varchar(40)
constraint c_color check (color in ('Red','Blue','Light Green','Yellow')));
create table marina
(mid integer not null constraint m_key primary key,
name varchar(40) not null,
capacity integer);
create table sailor
(sid integer not null constraint c_sid primary key,
sname varchar(40),
rating integer
constraint c_rating check (rating between 1 and 10),
age real constraint
c_age check (age < 18 OR age = 18));
create table reservation
(sid integer not null constraint f_key1 references sailor(sid) on delete cascade,
bid integer not null constraint f_key2 references boat(bid) on delete restrict
constraint c_bid check (bid not in (999)),
mid integer constraint f_key3 references marina(mid) on delete set null,
r_date date not null constraint c_date check (r_date > '02/04/1998'),
constraint p_key primary key(sid,bid,r_date));
INSERT INTO sailor(sid,sname,rating,age) VALUES (2, 'John', 6, 17);
INSERT INTO sailor(sid,sname,rating,age) VALUES (11, 'Mary', 10, 18);
INSERT INTO sailor(sid,sname,rating,age) VALUES (12, 'TH', 7, 14);
INSERT INTO sailor(sid,sname,rating,age) VALUES (13, 'John', 9, 18);
INSERT INTO sailor(sid,sname,rating,age) VALUES (1, 'Christin', 10, 17);
INSERT INTO sailor(sid,sname,rating,age) VALUES (15, 'Thod', 10, 13);
INSERT INTO sailor(sid,sname,rating,age) VALUES (16, 'Leonid', 5, 13);
INSERT INTO sailor(sid,sname,age) VALUES (17,'Left',17);
INSERT INTO sailor(sid,sname,rating,age) VALUES (19,'Polu',1,16);
INSERT INTO sailor(sid,sname,rating,age) VALUES (27,'Marinin',8,15);
INSERT INTO sailor(sid,sname,rating,age) VALUES (37,'Cos',8,14);
INSERT INTO marina(mid,name,capacity) VALUES(33,'Porto',300);
INSERT INTO marina(mid,name,capacity) VALUES(5,'Calam',105);
INSERT INTO marina(mid,name,capacity) VALUES(1,'Plat',32);
INSERT INTO marina(mid,name,capacity) VALUES(7,'Pos',19);
INSERT INTO marina(mid,name,capacity) VALUES(2,'Our',105);
INSERT INTO boat(bid,bname,color) VALUES(88,'Sof','Blue');
INSERT INTO boat(bid,bname,color) VALUES(17,'Ag','Light Green');
INSERT INTO boat(bid,bname,color) VALUES(13,'Panag','Yellow');
INSERT INTO boat(bid,bname,color) VALUES(1,'Αg.N','Red');
INSERT INTO boat(bid,bname,color) VALUES(72,'Christin','Red');
INSERT INTO boat(bid,bname,color) VALUES(19,'Dil','Light Green');
INSERT INTO boat(bid,bname,color) VALUES(77,'Αg.G','Blue');
INSERT INTO reservation(sid,bid,mid,r_date) VALUES(2,88,7,'1999-02-17');
INSERT INTO reservation(sid,bid,mid,r_date) VALUES(12,17,2,'1998-05-17');
INSERT INTO reservation(sid,bid,mid,r_date) VALUES(11,17,2,'1999-01-17');
INSERT INTO reservation(sid,bid,mid,r_date) VALUES(13,13,7,'2003-01-13');
INSERT INTO reservation(sid,bid,mid,r_date) VALUES(11,13,33,'2000-05-05');
INSERT INTO reservation(sid,bid,mid,r_date) VALUES(1,1,33,'2000-05-05');
INSERT INTO reservation(sid,bid,mid,r_date) VALUES(1,13,33,'2000-05-06');
INSERT INTO reservation(sid,bid,mid,r_date) VALUES(1,17,33,'2000-05-07');
INSERT INTO reservation(sid,bid,mid,r_date) VALUES(1,19,33,'2000-05-08');
INSERT INTO reservation(sid,bid,mid,r_date) VALUES(1,72,33,'2000-05-09');
INSERT INTO reservation(sid,bid,mid,r_date) VALUES(1,88,33,'2000-05-10');
INSERT INTO reservation(sid,bid,mid,r_date) VALUES(1,77,2,'2000-08-10');
INSERT INTO reservation(sid,bid,mid,r_date) VALUES(19,13,33,'1999-10-12');
INSERT INTO reservation(sid,bid,mid,r_date) VALUES(27,88,7,'2000-06-11');
INSERT INTO reservation(sid,bid,mid,r_date) VALUES(37,72,2,'2001-04-27');
This can be solved with an EXISTS sub-query:
select m.*
from marina m
where m.capacity > 200
and exists (select *
from reservation r
join boat b on r.bid = b.bid
where mid = m.mid
and b.color = 'Red')
where m.capacity > 200 only selects marinas with a capacity that is bigger than 200 (this is how I understand the "have tonnage bigger than 200")
The (co-related) sub-query then checks for reservations for each marina that were made for a red boat (that's how I understand the "that have for reservation red boat" part).
Online example

Can I reference this table?

I am trying to show amount paid for each tutor sorted by month and then by tutor id. I have the first part correct and can sort by month but cannot sort by tutor id because it is from a different table.
Here is the script for my tables:
create table match_history
(match_id number(3),
tutor_id number(3),
student_id number(4),
start_date date,
end_date date,
constraint pk_match_history primary key (match_id),
constraint fk1_match_history foreign key (tutor_id) references tutor(tutor_id),
constraint fk2_match_history foreign key (student_id) references student(student_id));
create table tutor_report
(match_id number(3),
month date,
hours number(3),
lessons number(3),
constraint pk_tutor_report primary key (match_id, month),
constraint fk1_tutor_report foreign key (match_id) references match_history(match_id));
insert into tutor values (100, '05-JAN-2017', 'Active');
insert into tutor values (101, '05-JAN-2017', 'Temp Stop');
insert into tutor values (102, '05-JAN-2017', 'Dropped');
insert into tutor values (103, '22-MAY-2017', 'Active');
insert into tutor values (104, '22-MAY-2017', 'Active');
insert into tutor values (105, '22-MAY-2017', 'Temp Stop');
insert into tutor values (106, '22-MAY-2017', 'Active');
insert into student values (3000, 2.3);
insert into student values (3001, 5.6);
insert into student values (3002, 1.3);
insert into student values (3003, 3.3);
insert into student values (3004, 2.7);
insert into student values (3005, 4.8);
insert into student values (3006, 7.8);
insert into student values (3007, 1.5);
insert into match_history values (1, 100, 3000, '10-JAN-2017', null);
insert into match_history values (2, 101, 3001, '15-JAN-2017', '15-MAY-2017');
insert into match_history values (3, 102, 3002, '10-FEB-2017', '01-MAR-2017');
insert into match_history values (4, 106, 3003, '28-MAY-2017', null);
insert into match_history values (5, 103, 3004, '01-JUN-2017', '15-JUN-2017');
insert into match_history values (6, 104, 3005, '01-JUN-2017', '28-JUN-2017');
insert into match_history values (7, 104, 3006, '01-JUN-2017', null);
insert into tutor_report values (1, '01-JUN-2017', 8, 4);
insert into tutor_report values (4, '01-JUN-2017', 8, 6);
insert into tutor_report values (5, '01-JUN-2017', 4, 4);
insert into tutor_report values (4, '01-JUL-2017', 10, 5);
insert into tutor_report values (1, '01-JUL-2017', 4, 2);
This is what I have so far:
Select (hours * 10) as amount paid from tutor_report group by month, tutor_id
however obviously I cannot just say tutor_id at the end.
You can join match_history to get the tutor_id.
But your statement and the query don't match. If you want to sort use ORDER BY.
SELECT tr.hours * 10 amount_paid
FROM tutor_report tr
INNER JOIN match_history mh
ON mh.match_id = tr.match_id
ORDER BY tr.month,
mh.tutor_id;
If you want to aggregate, hours needs to be argument to some aggregation function. Maybe you're after the sum of hours?
SELECT sum(tr.hours) * 10 amount_paid
FROM tutor_report tr
INNER JOIN match_history mh
ON mh.match_id = tr.match_id
GROUP BY tr.month,
mh.tutor_id;
If you are grouping based on columns on two tables,you need to join them on the matching Id and then use group by
Select (hours * 10) as amount paid
from tutor_report a
join match_history b on a. match_id = b.match_id
group by month, tutor_id

How to get fields from a table where its primary key is used in another table in 2 possible fields

I have 2 sql tables
CREATE TABLE users(userID INTEGER PRIMARY KEY AUTOINCREMENT, alias TEXT NOT NULL)
CREATE TABLE friends(userID1 INTEGER, userID2 INTEGER, PRIMARY KEY(userID1, userID2))
When 2 users want to be friends, I create a new relationship btw the 2 by inserting a row in the friends table. The order for the userID of the 2 friends in the row do not matter but it should be unique, whatever the order.
Question 1:
My second table do not currently reflect what I want. I mean I can do this and it's fine while I don't want it to be:
INSERT INTO friends VALUES(1,2);
INSERT INTO friends VALUES(2,1);
Is it possible to enforce this constraint in my sql table, or should I check with a query if there is not already a relationship in the reversed order.
Question 2:
What is the most optimal sql query to get the list of friends (userID and alias) if I have a userID, if I have for example:
INSERT INTO users VALUES(1, 'A');
INSERT INTO users VALUES(2, 'B');
INSERT INTO users VALUES(3, 'C');
INSERT INTO users VALUES(4, 'D');
INSERT INTO friends VALUES(1, 2);
INSERT INTO friends VALUES(2, 3);
INSERT INTO friends VALUES(4, 1);
INSERT INTO friends VALUES(2, 4);
I want:
For userID=1: (2, B) and (4, D)
For userID=2: (1, A), (3, C) and (4, D)
For userID=3: (2, B)
For userID=4: (1, A) and (2, B)
Bonus question: Can I improve the tables to better reflect what I want?
Thanks a lot!
One question at a time. Change your insert from this structure:
insert into table
(field1, field2, etc)
values
(value1, value2, etc)
to this structure
insert into table
(field1, field2, etc)
select distinct value1, value2, etc
from someSmallTable
where not exists
(subquery to check for existing rows)

What is wrong with this JOIN statement in SQL?

I am working on this tutorial about SQL. In Step 2 of 2, it is asked to use the JOIN command to link 2 people from the persons list using information from the friends list. I edited the provided code and obtained the code included below: the relevant part starts with select persons.fullname, persons2.fullname. However, the last paragraph of the code ('relevant code') does not yield any result nor error message. Am I doing something wrong?
Code
CREATE TABLE persons (
id INTEGER PRIMARY KEY AUTOINCREMENT,
fullname TEXT,
age INTEGER);
INSERT INTO persons (fullname, age) VALUES ("Bobby McBobbyFace", "12");
INSERT INTO persons (fullname, age) VALUES ("Lucy BoBucie", "25");
INSERT INTO persons (fullname, age) VALUES ("Banana FoFanna", "14");
INSERT INTO persons (fullname, age) VALUES ("Shish Kabob", "20");
INSERT INTO persons (fullname, age) VALUES ("Fluffy Sparkles", "8");
CREATE table hobbies (
id INTEGER PRIMARY KEY AUTOINCREMENT,
person_id INTEGER,
name TEXT);
INSERT INTO hobbies (person_id, name) VALUES (1, "drawing");
INSERT INTO hobbies (person_id, name) VALUES (1, "coding");
INSERT INTO hobbies (person_id, name) VALUES (2, "dancing");
INSERT INTO hobbies (person_id, name) VALUES (2, "coding");
INSERT INTO hobbies (person_id, name) VALUES (3, "skating");
INSERT INTO hobbies (person_id, name) VALUES (3, "rowing");
INSERT INTO hobbies (person_id, name) VALUES (3, "drawing");
INSERT INTO hobbies (person_id, name) VALUES (4, "coding");
INSERT INTO hobbies (person_id, name) VALUES (4, "dilly-dallying");
INSERT INTO hobbies (person_id, name) VALUES (4, "meowing");
CREATE table friends (
id INTEGER PRIMARY KEY AUTOINCREMENT,
person1_id INTEGER,
person2_id INTEGER);
INSERT INTO friends (person1_id, person2_id)
VALUES (1, 4);
INSERT INTO friends (person1_id, person2_id)
VALUES (2, 3);
/* personal contribution starts here
select persons.fullname,hobbies.name
from persons
join hobbies
on hobbies.person_id=persons.id;
/* select persons.fullname, persons2.fullname
from persons
join persons persons2
join friends
on persons.fullname=friends.person1_id and persons2.fullname=friends.person2_id; */
/* relevant code: */
select persons.fullname, persons2.fullname
from persons
join friends
on persons.fullname=friends.person1_id
join persons persons2
on persons2.fullname=friends.person2_id;
[tutorial (c) khanacademy.org]
join friends
on persons.fullname=friends.person1_id
You're only including friends whose person1_id equals a person's fullname. Since person1_id is an integer and fullname is text, those will never be equal. You probably want:
select persons.fullname, persons2.fullname
from persons
join friends
on persons.id=friends.person1_id
join persons persons2
on persons2.id=friends.person2_id;