how to merge 2 tables with one request - mysql

so i got 2 tables with following structure:
CREATE TABLE courses(
id bigint not null auto_increment,
title varchar(255) default '',
primary key(id)
);
CREATE TABLE course_dates(
id bigint not null auto_increment,
course_id bigint,
`date` date,
key idx(course_id,date),
primary key(id)
);
so courses are stored in first table and course dates in second (each course can have unlimited number of dates)
i need to get all course rows (with all its dates) at one time using one query
for example, if i have tables with such data:
courses:
id | title
1 | course#1
2 | course#2
course_dates:
id | course_id | date
1 | 1 | 2012-12-25
2 | 1 | 2012-12-27
3 | 1 | 2012-12-31
4 | 2 | 2012-12-23
5 | 2 | 2012-12-30
then i need result rows like this:
id | course_id | date | title
1 | 1 | 2012-12-25 | course#1
2 | 1 | 2012-12-27 | course#1
3 | 1 | 2012-12-31 | course#1
4 | 2 | 2012-12-23 | course#2
5 | 2 | 2012-12-30 | course#2

A simple INNER JOIN will do.
SELECT b.*, a.title
FROM Courses a
INNER JOIN Courses_Dates b
ON a.id = b.Course_ID
SQLFiddle Demo
SQLFiddle Demo (with ORDER BY clause)
To learn more about joins, see the link below
Visual Representation of SQL Joins

Related

What does the equal sign mean in this SQL Join statement?

I'm new to sql and do not understand what this join statement is doing. Does this statement ON people.state_code=states.state_abbrev mean that people.state_code and states.state_abbrev are now one?
SELECT people.first_name,
people.state_code, states.division
FROM people
JOIN states ON people.state_code=states.state_abbrev;
It will take the columns first_name and state_code from the table people and the column division from the table states and put them together in a join table where the entries in the state_code and state_abbrev columns match. The join table is produced only for display in response to this query; the underlying tables with the data entries are not amended.
In this case the '=' means equal (like values are equal) and is part of the join condition based on which data is retrieved by the select statement. You are 'linking' the two tables based on a condition so you can retrieve related data...
Relational data base - there are relations between tables and between data.
For example:
table_1
PERSON_ID FIRST_NAME LAST_NAME ADDRESS_ID
1 |John |Doe |2
table_2
ADRESS_ID STREET
1 | 5th Avenue
2 | 1st Street
SELECT FIRST_NAME, STREET
FROM table_1 t1
JOIN table_2 t2 ON t1.ADDRESS_ID = t2.ADDRESS_ID;
will return
John, 1st Street
Does this statement ON people.state_code=states.state_abbrev mean that people.state_code and states.state_abbrev are now one?
Answer: NO. people.state_code and states.state_abbrev should be the same value on the respective tables.
Let me give you an example taken from https://www.mysqltutorial.org/mysql-join/
Suppose you have below tables:
CREATE TABLE members (
member_id INT AUTO_INCREMENT,
members_name VARCHAR(100),
PRIMARY KEY (member_id)
);
CREATE TABLE committees (
committee_id INT AUTO_INCREMENT,
committees_name VARCHAR(100),
PRIMARY KEY (committee_id)
);
Some data examples:
+-----------+--------+
| member_id | members_name |
+-----------+--------+
| 1 | John |
| 2 | Jane |
| 3 | Mary |
| 4 | David |
| 5 | Amelia |
+-----------+--------+
+--------------+--------+
| committee_id | committees_name |
+--------------+--------+
| 1 | John |
| 2 | Mary |
| 3 | Amelia |
| 4 | Joe |
+--------------+--------+
To do the INNER JOIN we can use members_name and committees_name not the id because they are auto_increment and the data are not related.
So the query would be:
SELECT
m.member_id,
m.members_name AS member,
c.committee_id,
c.committees_name AS committee
FROM members m
INNER JOIN committees c ON c.name = m.name;
Giving below result:
+-----------+--------+--------------+-----------+
| member_id | member | committee_id | committee |
+-----------+--------+--------------+-----------+
| 1 | John | 1 | John |
| 3 | Mary | 2 | Mary |
| 5 | Amelia | 3 | Amelia |
+-----------+--------+--------------+-----------+
Conclusion: The values of the columns are equaly the same

Selecting the most popular destination of my database on mysql

I've created 3 tables:
CREATE TABLE participe
(
IDadherent INTEGER,
IDsortie INTEGER,
CONSTRAINT pk2 PRIMARY KEY (IDadherent, IDsortie)
);
CREATE TABLE sortie
(
IDsortie INTEGER PRIMARY KEY,
jour DATE,
Latitude_sortie FLOAT,
Longitude_sortie FLOAT
);
CREATE TABLE adherent
(
IDadherent INTEGER PRIMARY KEY,
nom VARCHAR(30),
prenom VARCHAR(30)
);
TL;DR:
Table 1) Adherent (this is the people potentially going to a set of destinations with adherentID as a primary key)
Table 2) Sortie (this is the table with the potential destinations with destinationID as a primary key)
Table 3) Participe (this table links both primary keys: AdherentID and destinationID
If I select the content of the table "participe" I get something like this:
+----------+------------+
| IDsortie | IDadherent |
+----------+------------+
| 5 | 1 |
| 5 | 3 |
| 5 | 5 |
| 4 | 2 |
| 3 | 1 |
| 3 | 4 |
| 3 | 5 |
| 2 | 3 |
| 2 | 5 |
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 0 | 6 |
+----------+------------+
I've attempted to order the above table and get a new table with the most popular destinations (IDsortie), expecting to get something like this:
+----------+----------------+
| IDsortie | Numeroadherent |
+----------+----------------+
| 5 | 3 |
| 4 | 1 |
| 3 | 3 |
| 2 | 2 |
| 1 | 3 |
| 0 | 1 |
+----------+----------------+
In order to achieve that glorious table I've used these queries (and failed miserably):
SELECT IDsortie, IDadherent
FROM participe
ORDER BY IDsortie DESC;
SELECT COUNT(IDsortie)
FROM participe
GROUP BY IDadherent
ORDER BY COUNT(IDadherent) ASC;
SELECT COUNT(IDsortie)
FROM
(SELECT COUNT(*) AS IDsortie
FROM participe
GROUP BY IDadherent) AS Results
One of the mysql mods has very kindly redirected me to other similar questions but I don't understand their answers, could someone please walk e through this (sorry for the inconvenience).
It looks like you want a single query:
SELECT IDsortie, COUNT(*) as Numeroadherent
FROM participe
GROUP BY IDsortie DESC
ORDER BY IDsortie DESC;
I'm not quite sure what your queries have to do with answering the question. Hence, it is unclear what your confusion is. The answer to your question is a simple GROUP BY query.
Try using the below query,
SELECT IDSortie
, COUNT(IDSortie) [Numeroadherent]
FROM Participe
GROUP
BY IDSortie
ORDER
BY IDSortie;

Remove duplication of rows while joining multiple tables - Mysql

media
id | title | ...
1 | a song |
2 | a video |
media setting
media_id | setting_id | chosen_option
1 | 1 | 2
1 | 2 | 3
2 | 1 | 1
2 | 2 | 4
So I have media table with various infromation about user uploaded media files and they have two settings 1.privacy( option-1 for public and option-2 for private) and 2.age-safty( option-3 is for all and option-4 is for adult only). Now when a user(adult) searching for a media, suppose with a title starts with a.....
Here is my query:
SELECT
m.id AS media_id, m.title AS media_title,
ms.setting_id AS setting, ms.chosen_option as opt
FROM media m
LEFT JOIN media_setting ms ON m.id = ms.media_id
WHERE m.title LIKE 'a%'
AND It will give me an output with duplicate rows one row with each setting which I don't want.
So what i want is :
media_id | media_title | setting_1 | option_for_1 | setting_2 | option_for_2
1 | a song | 1 | 2 | 2 | 3
2 | a video | 1 | 1 | 2 | 4
How can i achieve this? Thanks.
As per comments, I'd stick with the query you've got, and resolve the display issues in application code.
But anyway, here's a standard (and non-dynamic) approach in sql...
CREATE TABLE media
(id SERIAL PRIMARY KEY
,title VARCHAR(20) NOT NULL
);
INSERT INTO media VALUES
(1,'a song'),
(2,'a video');
DROP TABLE IF EXISTS media_setting;
CREATE TABLE media_setting
(media_id INT NOT NULL
,setting_id INT NOT NULL
,chosen_option INT NOT NULL
,PRIMARY KEY(media_id,setting_id)
);
INSERT INTO media_setting VALUES
(1,1,2),
(1,2,3),
(2,1,1),
(2,2,4);
SELECT m.*
, MAX(CASE WHEN s.setting_id = 1 THEN chosen_option END) option_for_1
, MAX(CASE WHEN s.setting_id = 2 THEN chosen_option END) option_for_2
FROM media m
LEFT
JOIN media_setting s
ON s.media_id = m.id
GROUP
BY m.id;
+----+---------+--------------+--------------+
| id | title | option_for_1 | option_for_2 |
+----+---------+--------------+--------------+
| 1 | a song | 2 | 3 |
| 2 | a video | 1 | 4 |
+----+---------+--------------+--------------+

Combining tables in mySQL to keep nulls [duplicate]

This question already has answers here:
How can I do a FULL OUTER JOIN in MySQL?
(15 answers)
Closed 4 years ago.
I have two tables below. I am looking to find all the combinations of store and newid in sales2 which are not present in sales1 and combine them with sales1.
I am looking for the end result to be:
store newid amount total
123 | 123 | 12.3 | 1
456 | 123 | 45.6 | 2
789 | adsf | 78.9 | 3
321 | 123f | NULL | NULL
789 | 1654 | NULL | NULL
Original Tables
CREATE TABLE sales1 (
id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
store VARCHAR(30) NOT NULL,
newid VARCHAR(30),
amount DOUBLE,
total INT
);
CREATE TABLE sales2 (
id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
store VARCHAR(30) NOT NULL,
newid VARCHAR(30),
amount DOUBLE
);
INSERT INTO sales1 (store, newid, amount, total) VALUES
('123','123', 12.3, 1),('456','123', 45.6, 2),('789','adsf', 78.9, 3);
INSERT INTO sales2 (store, newid, amount) VALUES
('123','123', Null),('456','123', Null),('321','123f', Null),('789','1654', Null);
We can use two different SELECT queries for this. First query will fetch all the rows from sales1 table.
Second would fetch the remaining rows from sales2 table, which do not exist in the sales1 table. We will use LEFT JOIN from sales2 to sales1 and consider only those rows where sales1.id is NULL after the Join.
We will eventually use UNION ALL to combine the result-set from both the queries.
Query
SELECT
s1.store, s1.newid, s1.amount, s1.total
FROM sales1 s1
UNION ALL
SELECT
s2.store, s2.newid, s2.amount, NULL AS total
FROM sales2 s2
LEFT JOIN sales1 s1
ON s2.store = s1.store AND
s2.newid = s1.newid
WHERE s1.id IS NULL;
Result
| store | newid | amount | total |
| ----- | ----- | ------ | ----- |
| 123 | 123 | 12.3 | 1 |
| 456 | 123 | 45.6 | 2 |
| 789 | adsf | 78.9 | 3 |
| 321 | 123f | | |
| 789 | 1654 | | |
View on DB Fiddle

Update table based on result of select on another table

I have two tables like this:
person:
id | name | sale | commission
1 | abc | 0 | 0
2 | xyz | 0 | 0
sale:
id | date | person_id | sale | commission
1 | 2016-05-01 | 1 | 10 | 1
2 | 2016-05-02 | 1 | 10 | 1
3 | 2016-05-03 | 1 | 10 | 1
4 | 2016-05-01 | 2 | 20 | 2
5 | 2016-05-02 | 2 | 20 | 2
6 | 2016-05-01 | 2 | 20 | 2
I want to update person table with single update query and change the table something like this:
person:
id | name | sale | commission
1 | abc | 30 | 3
2 | xyz | 60 | 6
I know I can sum sale like following but how to update following query result into person table directly.
SELECT person_id, SUM(sale), SUM(commission)
FROM sale
GROUP BY person_id;
As Strawberry said in the comments under your question, think long and hard before you save this information. It is denormalized, and it becomes stale. Rather, consider using it during report generation. Otherwise, well, as said, you may run into problems.
drop table if exists person;
create table person
( personId int auto_increment primary key,
name varchar(100) not null,
totSales decimal(9,2) not null,
totComm decimal(9,2)
);
insert person(name,totSales,totComm) values
('Joe',0,0),
('Sally',0,0);
-- just added persons 1 and 2 (auto_inc)
drop table if exists sale;
create table sale
( saleId int auto_increment primary key,
saleDate date not null,
personId int not null,
sale decimal(9,2) not null,
commission decimal(9,2) not null,
index(personId), -- facilitate a snappier "group by" later
foreign key (personId) references person(personId) -- Ref Integrity
);
insert sale(saleDate,personId,sale,commission) values
('2016-05-01',2,10,1),
('2016-05-01',1,40,4),
('2016-05-02',1,30,3),
('2016-05-07',2,10,1),
('2016-05-07',2,90,9);
-- the following dies on referential integrity, FK, error 1452 as expected
insert sale(saleDate,personId,sale,commission) values ('2016-05-01',4,10,1);
The update statement
update person p
join
( select personId,sum(sale) totSales, sum(commission) totComm
from sale
group by personId
) xDerived
on xDerived.personId=p.personId
set p.totSales=xDerived.totSales,p.totComm=xDerived.totComm;
The results
select * from person;
+----------+-------+----------+---------+
| personId | name | totSales | totComm |
+----------+-------+----------+---------+
| 1 | Joe | 70.00 | 7.00 |
| 2 | Sally | 110.00 | 11.00 |
+----------+-------+----------+---------+
2 rows in set (0.00 sec)
xDerived is merely an alias name. All derived tables need an alias name, whether or not you use the alias name explicitly.
UPDATE person
SET sale = (
SELECT SUM(s.sale) FROM sale s
WHERE s.person_id = person.id
);
works for me. See it in action at: http://ideone.com/F32oUU
EDIT for new version with additional aggregated column:
UPDATE person SET
sale = (
SELECT SUM(s.sale) FROM sale s
WHERE s.person_id = person.id
),
commission = (
SELECT SUM(s.commission) FROM sale s
WHERE s.person_id = person.id
);
http://ideone.com/yo1A9Y
This being said, I feel sure that a JOIN solution is better, and am hopeful another answerer will be able to post such a solution.