I have two tables.
support_table
+------+-------------+
| num | num_explain |
+------+-------------+
| 1 | 01 |
| 2 | 01 |
| 2 | 02 |
| 3 | 01 |
| 3 | 02 |
| 3 | 03 |
| 4 | 01 |
| 4 | 02 |
| 4 | 03 |
| 4 | 04 |
| 5 | 01 |
| 5 | 02 |
| 5 | 03 |
| 5 | 04 |
| 5 | 05 |
+------+-------------+
class_room
+-----------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+-------------+------+-----+---------+-------+
| seq_no | varchar(20) | YES | | NULL | |
| name | varchar(20) | YES | | NULL | |
| subjects | varchar(20) | YES | | NULL | |
| no_of_student | varchar(20) | YES | | NULL | |
| student_roll_no | varchar(20) | YES | | NULL | |
+-----------------+-------------+------+-----+---------+-------+
Now I've tried the below query to insert data into table class_room:
INSERT INTO class_room (seq_no,name,subjects,no_of_student,student_roll_no)
SELECT '1', 'class11', 'physics', num, num_explain FROM support_table
WHERE num='3';
this query works totally fine for me and it creates 3 rows. Now the table looks like below:
+---------+---------+----------+---------------+-----------------+
| seq_no | name | subjects | no_of_student | student_roll_no |
+---------+---------+----------+---------------+-----------------+
| 1 | class11 | physics | 3 | 01 |
| 1 | class11 | physics | 3 | 02 |
| 1 | class11 | physics | 3 | 03 |
+---------+---------+----------+---------------+-----------------+
Now I want to update this table, so I've tried the below code:
UPDATE class_room
SET name='class11', subjects='chemistry', no_of_student =
(SELECT num_explain FROM support_table WHERE num='4')
WHERE seq_no='1';
But this query IS showing that
Subquery returns more than one row.
Here I want that in class_room table no_of_student will be changed to '4' and student_roll_no will be upto '04' and instead of 3 rows, 4 rows will be created.
You have 3 rows in the table but you expect finally to get 4 rows.
This can't be done with an UPDATE statement which does not add new rows.
The simplest way to do what you want is to delete the current rows and then insert:
delete from class_room where no_of_student = 3;
insert into class_room (seq_no,name,subjects,no_of_student,student_roll_no)
select '1', 'class11','chemistry',num,num_explain
from support_table
where num='4';
See the demo.
| seq_no | name | subjects | no_of_student | student_roll_no |
| ------ | ------- | --------- | ------------- | --------------- |
| 1 | class11 | chemistry | 4 | 1 |
| 1 | class11 | chemistry | 4 | 2 |
| 1 | class11 | chemistry | 4 | 3 |
| 1 | class11 | chemistry | 4 | 4 |
= Can be used when the subquery returns only 1 value.
When subquery returns more than 1 value, you will have to use IN :
UPDATE class_room set name='class11',subjects='chemistry',no_of_student IN (select num_explain FROM support_table WHERE num='4')LIMIT 1 WHERE seq_no='1';
Example :
select *
from table
where id IN (multiple row query);
Another example :
SELECT *
FROM Students
WHERE Marks = (SELECT MAX(Marks) FROM Students) --A Example Subquery returning 1 value
SELECT *
FROM Students
WHERE Marks IN
(SELECT Marks
FROM Students
ORDER BY Marks DESC
LIMIT 10) --Example Subquery returning 10 values
A good explanation can be found here by #Raging bull
Related
I need to check that the steps of each project were done between the start and end dates of the project. (Write a query that allows a human to know if this is the case)
This is my code:
SELECT e.idetape,
e.idprojet,
e.datedebut,
e.datefin
FROM (SELECT idprojet,
datedebut,
datefin
FROM projet) AS p
LEFT JOIN etapexprojet AS e
ON e.datedebut < p.datedebut
AND e.datefin < p.datefin
ORDER BY idprojet;
The table of EtapexProjet (There is other date inside the table EtapexProjet ):
+---------+----------+-------------+--------------+--+
| idEtape | idProjet | dateDebut | dateFin | |
+---------+----------+-------------+--------------+--+
| 1 | 1 | 2011-07-01 | 2011-09-01 | |
| 1 | 2 | 2012-05-01 | 2012-05-10 | |
| 1 | 3 | 2011-11-01 | 2012-01-20 | |
| 2 | 1 | | | |
| 2 | 2 | | | |
| 2 | 3 | | | |
| 3 | 1 | | | |
| 3 | 2 | | | |
| 3 | 3 | | | |
| 4 | 1 | | | |
| 4 | 2 | | | |
| 5 | 2 | | | |
+---------+----------+-------------+--------------+--+
The table of Projet:
+----------+----------+-----------+------------+------------+---------------+--+
| idProjet | idClient | nomProjet | dateDebut | dateFin | idResponsable | |
+----------+----------+-----------+------------+------------+---------------+--+
| 1 | 321 | Devl. | 2011-08-01 | | 1876 | |
| 2 | 321 | Maint. | 2012-05-01 | 2012-07-23 | 2231 | |
| 3 | 345 | Devl.2 | 2011-11-01 | | 2231 | |
+----------+----------+-----------+------------+------------+---------------+--+
My expected results is that to check/verify if the beginning and ending date of each idEtape is between the beginning date and the ending date of the projet its related.
You don't need to use a Derived Table (sub-select query), as you are not doing any sort of aggregation, etc on the projet table.
I believe that you are only concerned with the idetape values which lie inside the projet's datedebut and datefin.
You can change Left Join to Inner Join due to above mentioned point.
I have also increased the horizon of cases to check, as there is a possibility of datefin being NULL in either of the tables.
Try the following instead:
SELECT e.idetape,
e.idprojet,
e.datedebut,
e.datefin,
p.datedebut AS projet_datedebut,
p.datefin AS projet_datefin
FROM EtapexProjet AS e
JOIN Projet AS p
ON p.idprojet = e.idprojet
AND e.datedebut >= p.datedebut
AND (e.datefin <= p.datefin OR
p.datefin IS NULL OR
e.datefin IS NULL
)
ORDER BY e.idprojet,
e.idetape;
Please try the code below:
SELECT nomEtape, livrable, idEtape, idProjet
FROM Etape
WHERE idEtape= (SELECT MAX(idEtape)
FROM EtapexProjet
WHERE DISTINCT(idProjet)
);
I have the following tables that records the details of letters vs actions, taken for them.
letter table
+-----------+-------------+
| letter_id | description |
+-----------+-------------+
| 1 | A |
| 2 | B |
| 3 | C |
| 4 | D |
+-----------+-------------+
action table
+-----------+--------+------------+---------------+
| action_id | ref_no | date | action_status |
+-----------+--------+------------+---------------+
| 1 | 1 | 2018-09-20 | On-Going |
| 2 | 1 | 2018-09-22 | Finished |
| 3 | 3 | 2018-09-16 | On-Going |
| 4 | 4 | 2018-09-26 | On-Going |
| 5 | 4 | 2018-09-27 | Finished |
+-----------+--------+------------+---------------+
And need to get the following output
+-----------+-------------+------------+---------------+
| letter_id | description | date | action_status |
+-----------+-------------+------------+---------------+
| 1 | A | 2018-09-22 | Finished |
| 2 | B | - | Pending |
| 3 | C | 2018-09-16 | On-Going |
| 4 | D | 2018-09-27 | Finished |
+-----------+-------------+------------+---------------+
I used the following query
select letter.letter_id,letter.description, action.date, action.action_status
from letter
left join action on letter.letter_id=action.ref_no
where (date in
(
select max(date) from action
where letter.letter_id=action.ref_no
))
But the above query generate the following output
+-----------+-------------+------------+---------------+
| letter_id | description | date | action_status |
+-----------+-------------+------------+---------------+
| 1 | A | 2018-09-20 | On-Going |
| 1 | A | 2018-09-22 | Finished |
| 2 | B | - | Pending |
| 3 | C | 2018-09-16 | On-Going |
| 4 | D | 2018-09-26 | On-Going |
| 4 | D | 2018-09-27 | Finished |
+-----------+-------------+------------+---------------+
I can not understand what I am going wrong. Can anyone help me ?
DROP TABLE IF EXISTS action;
CREATE TABLE action
(action_id SERIAL PRIMARY KEY
,letter_id INT NOT NULL
,date DATE NOT NULL
,action_status VARCHAR(20) NOT NULL
);
INSERT INTO action VALUES
(1,101,'2018-09-20','On-Going'),
(2,101,'2018-09-22','Finished'),
(3,103,'2018-09-16','On-Going'),
(4,104,'2018-09-26','On-Going'),
(5,104,'2018-09-27','Finished');
SELECT x.*
FROM action x
JOIN
( SELECT letter_id, MAX(date) max_date FROM action GROUP BY letter_id ) y
ON y.letter_id = x.letter_id
AND y.max_date = x.date;
+-----------+-----------+------------+---------------+
| action_id | letter_id | date | action_status |
+-----------+-----------+------------+---------------+
| 2 | 101 | 2018-09-22 | Finished |
| 3 | 103 | 2018-09-16 | On-Going |
| 5 | 104 | 2018-09-27 | Finished |
+-----------+-----------+------------+---------------+
Presumably, you can figure out the rest
I have a mysql table that holds data for team games.
Objective:
Count the number of times other SquadID's have have shared the same Team value as SquadID=21
// Selections table
+--------+---------+------+
| GameID | SquadID | Team |
+--------+---------+------+
| 1 | 5 | A |
| 1 | 7 | B |
| 1 | 11 | A |
| 1 | 21 | A |
| 2 | 5 | A |
| 2 | 7 | B |
| 2 | 11 | A |
| 2 | 21 | A |
| 3 | 5 | A |
| 3 | 7 | B |
| 3 | 11 | A |
| 3 | 21 | A |
| 4 | 5 | A |
| 4 | 11 | B |
| 4 | 21 | A |
| 5 | 5 | A |
| 5 | 11 | B |
| 5 | 21 | A |
| 6 | 5 | A |
| 6 | 11 | B |
| 6 | 21 | A |
+--------+---------+------+
// Desired Result
+---------+----------+
| SquadID | TeamMate |
+---------+----------+
| 5 | 6 |
| 7 | 0 |
| 11 | 3 |
| 21 | 6 |
+----------+---------+
I've attempted to use a subquery specifying the specific player I wish to compare with and because this subquery has multiple rows, I've used in instead of =.
// Current Query
SELECT
SquadID,
COUNT(Team IN (SELECT Team FROM selections WHERE SquadID=21) AND GameID IN (SELECT GameID FROM selections WHERE SquadID=21)) AS TeamMate
FROM
selections
GROUP BY
SquadID;
The result I'm getting is the number of Games a user has played rather than the number of games a user has been on the same team as SquadID=21
// Current Result
+---------+----------+
| SquadID | TeamMate |
+---------+----------+
| 5 | 6 |
| 7 | 3 |
| 11 | 6 |
| 21 | 6 |
+---------+----------+
What am I missing?
// DESCRIBE selections;
+---------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+---------+------+-----+---------+-------+
| GameID | int(11) | NO | PRI | 0 | |
| SquadID | int(4) | NO | PRI | NULL | |
| Team | char(1) | NO | | NULL | |
| TeamID | int(11) | NO | | 1 | |
+---------+---------+------+-----+---------+-------+
General rule is to avoid nested selects and look for a better way of logically arranging joins. Lets look at a cross join:
From selections s1
inner join selects s2 on s1.gameid = s2.gameid and s1.team = s2.team
This will produce a cross joined list of each squadID that participated with another squadID (IE: they were in the same game and on same team). We are only interested in the times where the squad participated with squad 21, so add a where clause:
where s2.squadid = 21
Then it's simply choosing the field/count you want:
select s1.squad, count(1) as teammate
any aggregate needs a group by
group by s1.squad
Combine it together and give a go. Oddly, this will produce a list where squad 21 will be showing as playing on it's own team all 6 times. Adding a where clause can eliminate this
where s1.squadid <> s2.squadid
SELECT SquadID, count(t1.team) as TeamMate
FROM selections as t1 join
(select distinct team, gameid from selections where SquadID=21) as t2
on t1.Team=t2.Team and t1.Gameid=t2.Gameid
GROUP BY SquadID
I have been working with SQL joins and kinda stuck with following scenario:
Table 1: PK(ID, GRADE)
| ID | Grade | Student_Count |
| 1 | 10th | 20 |
| 1 | 9th | 20 || 2 | 10th | 20 || 2 | 9th | 20 |
Table 2:PK(ID, Grade, Visited_Date)
| ID | Grade | Visited | Visit_Date |
| 1 | 10th | Yes | 25-Dec-2015 |
| 1 | 10th | No | 26-Dec-2015 |
| 1 | 9th | Yes | 28-Dec-2015 |
| 1 | 9th | No | 29-Dec-2015 |
| 2 | 10th | Yes | 27-Dec-2015 |
| 2 | 9th | No | 30-Dec-2015 |
What i need is a SELECT query which returns data from both the tables for a given ID in such a way that output rows should match the data of the Table 2 (no all possible combinations like cross/dot product) along with non-common columns from Table 1.
For example for ID "1" the output should be:
| ID | Grade | Student_Count | Visited | Visit_date |
| 1 | 10th | 20 | Yes | 25-Dec-2015 |
| 1 | 10th | 20 | No | 26-Dec-2015 |
| 1 | 9th | 20 | Yes | 28-Dec-2015 |
| 1 | 9th | 20 | No | 29-Dec-2015 |
Note: There is no foreign key association between both the tables.
You have to JOIN both tables on the id and grade fields.
SELECT b.ID, b.Grade, a.Student_Count, b.Visited, b.Visit_date
FROM table2 b
INNER JOIN table1 a
ON a.ID = b.ID AND a.Grade = b.Grade
ORDER BY a.ID
Maybe this will be an easy one for some of you MySQL masters who see this stuff like a level 3 children's book.
I have multiple tables that I'm joining to produce statistical data for a report and I'm getting tripped up at the moment trying to figure it out. It's obviously imperative the figures are correct because it impacts a number of decisions going forward.
Here's the lay of the land (not the full picture, but you'll get the point):
Affiliate Table
+----+-----------+------------+---------------------+
| id | firstname | lastname | created_date |
+----+-----------+------------+---------------------+
| 1 | Mike | Johnson | 2010-11-22 17:44:37 |
| 2 | Trevor | Wilson | 2010-12-23 16:24:24 |
| 3 | Bob | Parker | 2011-11-04 10:33:49 |
+----+-----------+------------+---------------------+
Now our query should only find results for Bob Parker (id 3) so I'll only show example results for Bob.
Affiliate Link Table
+-----+-----------+--------------+-----------+----------+---------------------+
| id | parent_id | affiliate_id | link_type | linkhash | created_date |
+-----+-----------+--------------+-----------+----------+---------------------+
| 21 | NULL | 3 | PRODUCT | fa2e82a7 | 2011-06-15 16:18:37 |
| 27 | NULL | 3 | PRODUCT | 55de2ae7 | 2011-06-23 01:03:00 |
| 28 | NULL | 3 | PRODUCT | 02cae72f | 2011-06-23 01:03:00 |
| 29 | 27 | 3 | PRODUCT | a4dfb2c8 | 2011-06-23 01:03:00 |
| 30 | 28 | 3 | PRODUCT | 72cea1b2 | 2011-06-23 01:03:00 |
| 36 | 21 | 3 | PRODUCT | fa2e82a7 | 2011-06-23 01:07:03 |
| 59 | 21 | 3 | PRODUCT | ec33413f | 2011-11-04 17:49:17 |
| 60 | 27 | 3 | PRODUCT | f701188c | 2011-11-04 17:49:17 |
| 69 | 21 | 3 | PRODUCT | 6dfb89fd | 2011-11-04 17:49:17 |
+-----+-----------+--------------+-----------+----------+---------------------+
Affiliate Stats
+--------+--------------+--------------------+----------+---------------------+
| id | affiliate_id | link_id | order_id | type | created_date |
+--------+--------------+---------+----------+----------+---------------------+
| 86570 | 3 | 21 | NULL | CLICK | 2013-01-01 00:07:31 |
| 86574 | 3 | 21 | NULL | PAGEVIEW | 2013-01-01 00:08:53 |
| 86579 | 3 | 21 | 411 | SALE | 2013-01-01 00:09:52 |
| 86580 | 3 | 36 | NULL | CLICK | 2013-01-01 00:09:55 |
| 86582 | 3 | 36 | NULL | PAGEVIEW | 2013-01-01 00:09:56 |
| 86583 | 3 | 28 | NULL | CLICK | 2013-01-01 00:11:04 |
| 86584 | 3 | 28 | NULL | PAGEVIEW | 2013-01-01 00:11:04 |
| 86586 | 3 | 30 | NULL | CLICK | 2013-01-01 00:30:18 |
| 86587 | 3 | 30 | NULL | PAGEVIEW | 2013-01-01 00:30:20 |
| 86611 | 3 | 69 | NULL | CLICK | 2013-01-01 00:40:19 |
| 86613 | 3 | 69 | NULL | PAGEVIEW | 2013-01-01 00:40:19 |
| 86619 | 3 | 69 | 413 | SALE | 2013-01-01 00:42:12 |
| 86622 | 3 | 60 | NULL | CLICK | 2013-01-01 00:46:00 |
| 86624 | 3 | 60 | NULL | PAGEVIEW | 2013-01-01 00:46:01 |
| 86641 | 3 | 60 | NULL | PAGEVIEW | 2013-01-01 00:55:58 |
| 86642 | 3 | 30 | 415 | SALE | 2013-01-01 00:56:35 |
| 86643 | 3 | 28 | NULL | PAGEVIEW | 2013-01-01 00:56:43 |
| 86644 | 3 | 60 | 417 | SALE | 2013-01-01 00:56:52 |
+--------+--------------+---------+----------+----------+---------------------+
Orders
+------+--------------+---------+---------------------+
| id | affiliate_id | total | created_date |
+------+--------------+---------+---------------------+
| 411 | 3 | 138.62 | 2013-01-01 00:09:50 |
| 413 | 3 | 312.87 | 2013-01-01 00:09:52 |
| 415 | 3 | 242.59 | 2013-01-01 00:09:55 |
| 417 | 3 | 171.18 | 2013-01-01 00:09:55 |
+------+--------------+---------+---------------------+
Now the results that I need should look like this (only show main/parent link id)
+---------+---------+
| link_id | total |
+---------+---------+
| 21 | 451.49 | <- 1 order from parent (21), 1 from child (69)
| 27 | 171.18 | <- 1 order from child (69)
| 28 | 242.59 | <- 1 order from child (30)
+---------+---------+
I'm not quite sure how to write the query so that I can sum where affiliate_link.id and affiliate_link.parent_id are combined. Is this even possible with a couple of JOINs and GROUPing?
I'm not too sure why you have denormalised affiliate_id (by placing it in each table) and, therefore, whether one can rely on all Stats and Orders that stem from a particular Link to have the same affiliate_id as that Link.
If it's possible, I'd suggest changing the AffiliateLink.parent_id column such that parent records point to themselves (rather than NULL):
UPDATE AffiliateLink SET parent_id = id WHERE parent_id IS NULL
Then it's a simple case of joining and grouping:
SELECT AffiliateLink.parent_id AS link_id,
SUM(Orders.total) AS total
FROM AffiliateLink
JOIN AffiliateStats ON AffiliateStats.link_id = AffiliateLink.id
JOIN Orders ON Orders.id = AffiliateStats.order_id
WHERE AffiliateLink.affiliate_id = 3
GROUP BY AffiliateLink.parent_id
See it on sqlfiddle.
If it's not possible to make the change, you can effectively create the resulting AffiliateLink table using UNION (but beware the performance implications, as MySQL will not be able to use indexes on the result):
(
SELECT parent_id, id, affiliate_id FROM AffiliateLink WHERE parent_id IS NOT NULL
UNION ALL
SELECT id , id, affiliate_id FROM AffiliateLink WHERE parent_id IS NULL
) AS AffiliateLink
See it on sqlfiddle.