using join to get records of a specific fk - mysql

I have a table of ParentsSchoolContact, which a parentId have foreign key to the parentId:
CREATE TABLE ParentsSchoolContact (
contactId int NOT NULL AUTO_INCREMENT,
parentId int NOT NULL,
name varchar(60) NOT NULL,
age varchar(60) NOT NULL,
PRIMARY KEY (contactId),
FOREIGN KEY (parentId) REFERENCES Parent(parentId)
);
and I have a parent and contact table that keeps the relation between a kid and a parent:
CREATE TABLE ParentAndContact (
parentId int NOT NULL,
contactId int NOT NULL,
PRIMARY KEY (contactId, parentId)
);
I want to get all the contacts related to a specific parent that i have its id, would that be the right query?
SELECT c.name, c.age
FROM ParentsSchoolContact c
INNER JOIN ParentAndKid pc ON pc.contactId = c.contactId
AND c.parentId = myParentVariable
AND pc.parentId = myParentVariable
wanted to make sure this query dosent fall in some case you could think about :)
thanks!

For me, i see that the ParentAndContact table is redundant. Usually the Parents details are in one table and ContactID/Kids details are in another table (having attributes eg. courses which the kids enrolled, details of the kids).
Assuming that you want to get all the contacts related to a specific parent that you have its id from the available tables (ParentsSchoolContact,ParentAndContact), You can just write a simple query to retrieve the information from ParentsSchoolContact table as of below:-
select contactId, parentId, name, age
from ParentsSchoolContact
where parentId = myParentVariable
Do let me know if i miss out anything.

Related

Select the oldest from join

I'm making my own archive system. Here is how it looks so far. I have following SQL tables:
CREATE TABLE items (
id int NOT NULL AUTO_INCREMENT,
serial_number varchar(255) NOT NULL,
catalog_number varchar(255) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE entities (
id int NOT NULL AUTO_INCREMENT,
table_name varchar(255) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE entities_relations (
id int NOT NULL AUTO_INCREMENT,
table_name varchar(255) NOT NULL,
entity_id int NOT NULL,
row_id int NOT NULL,
PRIMARY KEY (id)
);
Each entity where table_name is "items" has at least one item matched via entities_relations. entities_relations shows how many relations are between one entity and items. After saving an item it saves a new Item which is a copy of the previous one and adds a relation. Copies (archive items) don't create a new entity, they create only relation. The oldest relation is the original item.
The following SQL syntax shows me items list. It's wrong because it shows me all items, even if they are archived. I would like to display only the original ones. How can I change it to be able to display only original ones and ignore archives?
SELECT
items.*,
FROM
items
LEFT JOIN entities_relations ON
entities_relations.row_id = items.id
LEFT JOIN entities ON
entities.id = entities_relations.entity_id
WHERE
entities.name = 'items'
ORDER BY
entities.id DESC,
entities_relations.entity_id DESC
LIMIT 0, 50

Trying to find 3 columns from 3 different tables

I have the following 3 tables:
CREATE TABLE Pins (
email varchar(100) NOT NULL,
boardID int NOT NULL,
));
CREATE TABLE Boarders (
email varchar(100) NOT NULL,
boardID int NOT NULL,
FOREIGN KEY (categoryName) REFERENCES Category (name));
CREATE TABLE User (
email varchar(100) NOT NULL,
name varchar(50),
PRIMARY KEY (email));
I am wanting to make the query search results this: for each Pin, show the description
This obviously is not working, but any suggestions on how to get the above to display?
select p.description ,c.title, u.name from PushPin p,CorkBoard c, User u
where c.email=u.email and c.email =p.email and c.boardID = p.boardID
order by p.description
Yes, this will require you to join the three tables.
Something like the below code should work.
Just defining the Foreign key relations does not mean you would not need to join while querying.
SELECT PP.description, CB.title, U.name
FROM PushPin PP JOIN CorkBoard CB ON PP.boardID = CB.boardID
JOIN USSER U ON PP.email = U.email
WHERE description like '$search'
ORDER BY description;

Trouble with JOINS in mysql

I was working in mySQL and made a fake database for reviews, reviewers and tv series. So I made 3 different tables, one for reviewers, one for reviews and one for the series.
CREATE TABLE reviewers
(
id INT AUTO_INCREMENT PRIMARY KEY,
first_name VARCHAR(100) NOT NULL,
last_name VARCHAR(150) NOT NULL
);
CREATE TABLE series
(
id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(100) NOT NULL,
released_year YEAR(4),
genre VARCHAR(50)
);
CREATE TABLE reviews(
id INT AUTO_INCREMENT PRIMARY KEY,
rating DECIMAL(2,1),
series_id INT,
reviewer_id INT,
FOREIGN KEY(series_id) REFERENCES series(id),
FOREIGN KEY(reviewer_id) REFERENCES reviewers(id)
);
The thing that I wanted to ask is, how can I get the highest rating from each reviewer and in which show they gave it?
UPDATE
I came up with this code
SELECT first_name,last_name,title, a.series_id,a.rating FROM
( SELECT series_id,MAX(rating) AS max FROM reviews
GROUP BY series_id ) AS b
INNER JOIN reviews AS a
ON a.series_id=b.series_id AND a.rating=b.max
INNER JOIN reviewers
ON reviewers.id=a.reviewer_id
INNER JOIN series
ON series.id=a.series_id
GROUP BY series_id;
which gives me the max rating in each series and who gave that rating

SQL select entries in other table linked by foreign keys

I have redesigned my database structure to use PRIMARY and FOREIGN KEYs to link the entries in my 3 tables together, and I am having problems trying to write queries to select data in one table given data in a another table. Here is an example of my 3 CREATE TABLE statements:
CREATE TABLE IF NOT EXISTS players (
id INT(10) NOT NULL AUTO_INCREMENT,
username VARCHAR(16) NOT NULL,
uuid VARCHAR(200) NOT NULL DEFAULT 0,
joined TIMESTAMP DEFAULT 0,
last_seen TIMESTAMP DEFAULT 0,
PRIMARY KEY (id)
);
/* ^
One |
To
| One
v
*/
CREATE TABLE IF NOT EXISTS accounts (
id INT(10) NOT NULL AUTO_INCREMENT,
account_id INT(10) NOT NULL,
pass_hash VARCHAR(200) NOT NULL,
pass_salt VARCHAR(200) NOT NULL,
created BIGINT DEFAULT 0,
last_log_on BIGINT DEFAULT 0,
PRIMARY KEY (id),
FOREIGN KEY (account_id) REFERENCES players(id) ON DELETE CASCADE
) ENGINE=InnoDB;
/* ^
One |
To
| Many
v
*/
CREATE TABLE IF NOT EXISTS purchases (
id INT(10) NOT NULL AUTO_INCREMENT,
account_id INT(10) NOT NULL,
status VARCHAR(20) NOT NULL,
item INT NOT NULL,
price DOUBLE DEFAULT 0,
description VARCHAR(200) NOT NULL,
buyer_name VARCHAR(200) NOT NULL,
buyer_email VARCHAR(200) NOT NULL,
transaction_id VARCHAR(200) NOT NULL,
payment_type VARCHAR(20) NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (account_id) REFERENCES accounts(account_id) ON DELETE CASCADE
) ENGINE=InnoDB;
Say for example, I want to select all the usernames of users who purchased anything greater than $30. All the usernames are stored in the players table, which is linked to the accounts table and that is linked to the purchases table. Is this this the best way to design this relational database? If so, how would I run queries similar to the above example?
I was able to get get all of a users purchase history given their username, but I did it with 2 sub-queries... Getting that data should be easier than that!
Here is the SELECT query I ran to get all of a players purchase data:
SELECT *
FROM purchases
WHERE account_id = (SELECT id FROM accounts WHERE account_id = (SELECT id FROM players WHERE username = 'username'));
Also, when I try to make references to the other tables using something like 'players.username', I get an error saying that the column doesn't exist...
I appreciate any help! Thanks!
Your design is ok in my opinion. The relation between players and account is one-to-many and not one-to-one since this way, you can have two tuples referencing a single player.
I would write the query you need as:
SELECT DISTINCT p.id, p.username
FROM players p INNER JOIN accounts a ON (p.id = a.account_id)
INNER JOIN purchases pc ON (a.id = pc.account_id)
WHERE (pc.price > 30);
As Sam suggested, I added DISTINCT to avoid repeating id and username in case a user have multiple purchases.
Note the id is here to avoid confusion among repeated usernames.

selecting a user of every type

I have a query against two databases that I'm trying to execute. The first table is just user information and is referenced by a privilege table. For my query I'm trying to find a set of super users, they are users that have every current privilege in the privilege table. It is set up as follows:
create table MEMBER
( id int not null,
name varchar(10),
bdate date,
sex char,
pc_id int not null,
PRIMARY KEY (mid),
FOREIGN KEY (pc_id) REFERENCES PLEDGECLASS(id))
create table MEMBER_PRIVILEGE
( mid int not null,
pid int not null,
PRIMARY KEY (mid,pid),
FOREIGN KEY (mid) REFERENCES MEMBER(id),
FOREIGN KEY (pid) REFERENCES PRIVILEGE(id))
create table PRIVILEGE
( id int,
pname varchar(15)
PRIMARY KEY(id))
Although obviously the incorrect query, I'm trying to do something equivalent to the following:
Select name
From MEMBER,MEMBER_PRIVILEGE
Where id=mid AND pid = ALL (select id
From PRIVILEGE);
SELECT *
FROM MEMBER
WHERE NOT EXISTS (
SELECT *
FROM MEMBER_PRIVILEGE LEFT JOIN PRIVILEGE ON MEMBER_PRIVILEGE.pid = PRIVILEGE.id)
WHERE MEMBER_PRIVILEGE.mid = MEMBER.id AND PRIVILEGE.id IS NULL
)
Try this ::
Select name, (select count(id) from PRIVILIGE) as p_count
From MEMBER m
inner join MEMBER_PRIVILEGE mp on (m.id=mp.mid)
group by mp.mid having count(*) = p_count;