Insert values from one table to another by query - mysql

I have two tables Like Below
CREATE TABLE projectlist(ProjectId INT NOT NULL PRIMARY KEY,
ProjectName VARCHAR(50),
Location VARCHAR(50));
CREATE TABLE LocationList(LocaId INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
ProjectId INT,
Location VARCHAR(50));
The Values in the table are as Below
INSERT INTO projectlist(ProjectId, ProjectName)
VALUES(1, 'Project A'),
(2, 'Project B'),
(3, 'Project C'),
(4, 'Project D'),
(5, 'Project E'),
(6, 'Project F'),
(7, 'Project G'),
(8, 'Project H');
INSERT INTO LocationList(ProjectId, Location)
VALUES(1, 'Location A'),
(1, 'Location C'),
(2, 'Location C'),
(2, 'Location B'),
(2, 'Location A'),
(3, 'Location B'),
(4, 'Location C'),
(5, 'Location D'),
(6, 'Location A'),
(6, 'Location B'),
(7, 'Location B'),
(8, 'Location D'),
(8, 'Location A');
I want a Insert Query which inserts First LocationList.Location into projectlist.Location for their respective project relating on project id.
So the table projectlist after running query is
ProjectName Location
Project A Location A
Project B Location C
Project C Location B
Project D Location C
Project E Location D
Project F Location A
Project G Location B
Project H Location D
I tried a SQL query which bring the First Location from LocationList table as below.
SELECT DISTINCT MNPCL.Location, MNP.ProjectId
FROM LocationList MNPCL RIGHT OUTER JOIN
projectlist MNP ON MNP.ProjectId = MNPCL.ProjectId
GROUP BY MNP.ProjectName
How to write a query which perform insert in the projectlist Location
Thanks For Reply

Here is a SQLFiddle demo
update projectlist
join
(
select LocationList.ProjectID,LocationList.Location
from LocationList
join
(select LocationList.ProjectID,min(LocaId) minLocaId
from LocationList
group by LocationList.ProjectID) l1
on LocationList.LocaId=l1.minLocaID
) l2 on projectList.ProjectID=l2.ProjectID
SET ProjectList.Location=l2.Location

try:
UPDATE projectlist AS prj SET Location =
(SELECT Location FROM LocationList AS lst WHERE lst.ProjectId = prjProjectId ORDER BY Location DESC LIMIT 1)
since your projects have more than one location in LocationList and you can only have one location in your projectlist table you have to limit the result set to one row.

This will work for you...
UPDATE projectlist AS prj SET Location = (
SELECT group_concat(locationlist.Location SEPARATOR ',') as loc FROM `locationlist` left join projectlist using (ProjectId)
group by locationlist.ProjectId)

Related

How to get the value of a different ID that is acquired during the SELECT statement?

I have created an entity tblPerson and from this entity I need to get the bGroup of t.adminID and the bGroup from the d.personID. I have tried the below query but it's not returning anything.
`
SELECT t.adminID, p.firstName, p.lastName, t.transID, t.transDate, t.donationID, p.bGroup, b.bankName, d.personID AS 'Donor ID', 'Donor BGroup'
FROM tblTrans t
JOIN tblAdmin a ON t.adminID = a.adminID
JOIN tblPerson p ON a.personID = p.personID
JOIN tblDonation d ON t.donationID = d.donationID
JOIN tblBank b ON d.bankID = b.bankID
WHERE 'Donor BGroup' IN
(SELECT p.bGroup
FROM tblPerson p
JOIN tblDonation d ON p.personID = d.personID
JOIN tblTrans t ON d.donationID = t.donationID);
`
When I execute the subquery, it gives me the bGroup of the d.personID, what do you think is going on, and maybe any alternatives, please?
Sample Data
INSERT INTO tblPerson (personID, firstName, lastName, bGroup)
VALUES ('1A', 'John', 'Doe', 'XY'),
('2A', 'Joe', 'Bishop', 'AB'),
('1B', 'Elly', 'James', 'OP'),
('2B', 'Andre', 'Butch', 'XY'),
('3A', 'Amy', 'Gree', 'AB'),
('3B', 'Alfred', 'Black', 'OP'),
('4C', 'James', 'Brown', 'XY');
INSERT INTO tblAdmin (adminID, personID, description)
VALUES (1, '1A', 'Whatever.'),
(2, '1B', ''),
(3, '4C', 'Anything.'),
(4, '1A', '');
INSERT INTO tblDonation (donationID, bankID, personID, donationDate)
VALUES (1, 1, '3B', '2018-12-27'),
(2, 1, '2A', '2022-12-28'),
(3, 2, '3A', '2022-03-23'),
(4, 2, '4C', '2022-06-19'),
(5, 3, '1B', '2022-08-19'),
(6, 3, '2B', '2022-08-08'),
(7, 3, '3B', '2022-07-20'),
(8, 2, '4C', '2022-11-26'),
(9, 1, '3B', '2022-11-26'),
(10, 2, '2A', '2022-01-16');
INSERT INTO tblBank (bankID, bankName)
VALUES (1, 'Bank 1'),
(2, 'Bank 2'),
(3, 'Bank 3');
INSERT INTO tblTrans (transID, transDate, donationID, adminID)
VALUES (1, '2022-12-31', 1, 1),
(2, '2022-01-01', 2, 1),
(3, '2022-05-23', 3, 2),
(4, '2022-05-23', 4, 2),
(5, '2022-07-09', 5, 3),
(6, '2022-08-20', 6 4),
(7, '2022-12-27', 7,4);
Sample ERD Diagram
Expected Output
Example: 1, John, Doe, 1, 2022-12-31, 1, XY, Bank 1, 3B, OP.
Your WHERE 'Donor BGroup' IN (SELECT...) clause evaluates to WHERE false, because you don't have any rows with that value in tblPerson.bGroup. So, your SELECT statement's result set is empty.
It's hard to puzzle out your requirement from your question.
I managed to find the solution. Since I needed to call the same table twice with different IDs I had to create two aliases and JOIN the table twice, like so:
SELECT t.adminID, person.firstName, person.lastName, t.transID, t.transDate, t.donationID, person.bGroup, b.bankName, donor.personID AS 'Donor ID', donor.bGroup AS 'Donor BGroup'
FROM tblTrans t
JOIN tblAdmin a ON t.adminID = a.adminID
JOIN tblPerson person ON a.personID = person.personID
JOIN tblDonation d ON t.donationID = d.donationID
JOIN tblPerson donor ON
JOIN tblBank b ON d.bankID = b.bankID;

Group_Concat() from same DB

i'm doing a query on DB that i want return to me the group concat of the duplicate category for example in this table
I want the result of the concats parent from the same table in MySQL as this way
Hello Please test this:
CREATE TABLE Monopoly (Id INT,Name VARCHAR(30),Platform_ID INT,Parent_Name VARCHAR(30));
INSERT INTO Monopoly VALUES
(1, 'Rosatis', 1113080,'Rosatis Franchase'),
(2, 'Rosatis', 1113080,'Rosatis Global'),
(3, 'Rosatis', 1113080,'Rosatis USA'),
(4, 'Macianos Food', 1125676,'Rosatis Franchase'),
(5, 'Macianos Food', 1125676,'Rosatis Global'),
(6, 'Aurora BAR', 1452355,'Bar Grill Global'),
(7, 'Aurora BAR', 1452355,'USA Group'),
(8, 'Aurora BAR', 1452355,'Food Group');
Full Code:
SELECT M1.Id,M1.Name,M1.Platform_ID,M1.Parent_Name,Family_Name
FROM Monopoly M1
JOIN (SELECT Name, GROUP_CONCAT(DISTINCT Parent_Name) AS Family_Name FROM Monopoly GROUP BY Name) AS M2 ON M1.Name = M2.Name
GROUP BY Id,Name,Platform_ID,Parent_Name;
If we test the code:

MySQL update multiple rows based on id

In a table in MySQL I'm trying to update a specific field based on the id.
The table has more than 5,000 rows and many fields. One of the fields is "id" and another one that I want to update is called "category" which right now all of them are NULL and I want to update all of them.
my backup mysql file that I want to use has only "id" and "category" which they are like this:
INSERT INTO `products` (`id`, `category`) VALUES
(3, 1),
(4, 1),
(5, 2),
(6, 1),
(7, 5),
(8, 1),
(9, 6),
(10, 1),
...
(5000, 3);
I want to update the "category" field in my table according to the id's in this list and because there is more than 5,000 rows I don't want to change each record manually.
Right now in my table all the "category" fields are NULL and I want to update or give new information to the "category" fields using the file that I have.
The easiest is to use a Temporary table :
CREATE TEMPORARY TABLE temp_products (id int, category int ) ;
Then
INSERT INTO `temp_products` (`id`, `category`) VALUES
(3, 1),
(4, 1),
(5, 2),
(6, 1),
(7, 5),
(8, 1),
(9, 6),
(10, 1),
...
(5000, 3);
Now you just have to use an update with an inner join :
Update products p
INNER JOIN temp_products t_p ON t_p.id = p.id
SET p.category = t_p.category
if you want you can add a where clause :
Update products p
INNER JOIN temp_products t_p ON t_p.id = p.id
SET p.category = t_p.category
WHERE p.category IS NULL
Perhaps the better solution for you can be:
First of all, create temporary table
CREATE TABLE `products_tmp` (
`id` INT NOT NULL,
`category` INT NOT NULL,
PRIMARY KEY (`id`)
);
After that, perform inserts into generated temporary table:
INSERT INTO `products_tmp` (`id`, `category`) VALUES
(3, 1),
(4, 1),
(5, 2),
(6, 1),
(7, 5),
(8, 1),
(9, 6),
(10, 1),
...
(5000, 3);
after this, you can update all fields in your original table:
UPDATE products p
JOIN products_tmp pt ON p.id = pt.id
SET p.category = pt.category;
After this, you can delete temporary table
drop table products_tmp;

Select rows grouped by a column having max aggregate

Given the following data set, how would I find the email addresses that were references for the most ApplicationIDs that have an "Accepted" decision?
CREATE TABLE IF NOT EXISTS `EmailReferences` (
`ApplicationID` INT NOT NULL,
`Email` VARCHAR(45) NOT NULL,
PRIMARY KEY (`ApplicationID`, `Email`)
);
INSERT INTO EmailReferences (ApplicationID, Email)
VALUES
(1, 'ref10#test.org'), (1, 'ref11#test.org'), (1, 'ref12#test.org'),
(2, 'ref20#test.org'), (2, 'ref21#test.org'), (2, 'ref22#test.org'),
(3, 'ref11#test.org'), (3, 'ref31#test.org'), (3, 'ref32#test.org'),
(4, 'ref40#test.org'), (4, 'ref41#test.org'), (4, 'ref42#test.org'),
(5, 'ref50#test.org'), (5, 'ref51#test.org'), (5, 'ref52#test.org'),
(6, 'ref60#test.org'), (6, 'ref11#test.org'), (6, 'ref62#test.org'),
(7, 'ref70#test.org'), (7, 'ref71#test.org'), (7, 'ref72#test.org'),
(8, 'ref10#test.org'), (8, 'ref81#test.org'), (8, 'ref82#test.org')
;
CREATE TABLE IF NOT EXISTS `FinalDecision` (
`ApplicationID` INT NOT NULL,
`Decision` ENUM('Accepted', 'Denied') NOT NULL,
PRIMARY KEY (`ApplicationID`)
);
INSERT INTO FinalDecision (ApplicationID, Decision)
VALUES
(1, 'Accepted'), (2, 'Denied'),
(3, 'Accepted'), (4, 'Denied'),
(5, 'Denied'), (6, 'Denied'),
(7, 'Denied'), (8, 'Accepted')
;
Fiddle of same:http://sqlfiddle.com/#!9/03bcf2/1
Initially, I was using LIMIT 1 and ORDER BY CountDecision DESC, like so:
SELECT er.email, COUNT(fd.Decision) AS CountDecision
FROM EmailReferences AS er
JOIN FinalDecision AS fd ON er.ApplicationID = fd.ApplicationID
WHERE fd.Decision = 'Accepted'
GROUP BY er.email
ORDER BY CountDecision DESC
LIMIT 1
;
However, it occurred to me that I could have multiple email addresses that referred different "most accepted" decisions (i.e., a tie, so to speak), and those would be filtered out (is that the right phrasing?) with the LIMIT keyword.
I then tried a variation on the above query, replacing the ORDER BY and LIMIT lines with:
HAVING MAX(CountDecision)
But I realized that that's only half a statement: MAX(CountDecision) needs to be compared to something. I just don't know what.
Any pointers would be much appreciated. Thanks!
Note: this is for a homework assignment.
Update: To be clear, I'm trying to find value and count of Emails from EmailReferences. However, I only want rows that have FinalDecision.Decision = 'Accepted' (on matching ApplicantIDs). Based on my data, the result should be:
Email | CountDecision
---------------+--------------
ref10#test.org | 2
ref11#test.org | 2
For example...
SELECT a.*
FROM
( SELECT x.email
, COUNT(*) total
FROM emailreferences x
JOIN finaldecision y
ON y.applicationid = x.applicationid
WHERE y.decision = 'accepted'
GROUP
BY x.email
) a
JOIN
( SELECT COUNT(*) total
FROM emailreferences x
JOIN finaldecision y
ON y.applicationid = x.applicationid
WHERE y.decision = 'accepted'
GROUP
BY x.email
ORDER
BY total DESC
LIMIT 1
) b
ON b.total = a.total;
MySQL still lack window functions, but when version 8 is production ready, this becomes easier. So for fuure reference, or for those databases like Mariadb that already have window functions:
CREATE TABLE IF NOT EXISTS `EmailReferences` (
`ApplicationID` INT NOT NULL,
`Email` VARCHAR(45) NOT NULL,
PRIMARY KEY (`ApplicationID`, `Email`)
);
INSERT INTO EmailReferences (ApplicationID, Email)
VALUES
(1, 'ref10#test.org'), (1, 'ref11#test.org'), (1, 'ref12#test.org'),
(2, 'ref20#test.org'), (2, 'ref21#test.org'), (2, 'ref22#test.org'),
(3, 'ref30#test.org'), (3, 'ref31#test.org'), (3, 'ref32#test.org'),
(4, 'ref40#test.org'), (4, 'ref41#test.org'), (4, 'ref42#test.org'),
(5, 'ref50#test.org'), (5, 'ref51#test.org'), (5, 'ref52#test.org'),
(6, 'ref60#test.org'), (6, 'ref11#test.org'), (6, 'ref62#test.org'),
(7, 'ref70#test.org'), (7, 'ref71#test.org'), (7, 'ref72#test.org'),
(8, 'ref10#test.org'), (8, 'ref81#test.org'), (8, 'ref82#test.org')
;
CREATE TABLE IF NOT EXISTS `FinalDecision` (
`ApplicationID` INT NOT NULL,
`Decision` ENUM('Accepted', 'Denied') NOT NULL,
PRIMARY KEY (`ApplicationID`)
);
INSERT INTO FinalDecision (ApplicationID, Decision)
VALUES
(1, 'Accepted'), (2, 'Denied'),
(3, 'Accepted'), (4, 'Denied'),
(5, 'Denied'), (6, 'Denied'),
(7, 'Denied'), (8, 'Accepted')
;
select email, CountDecision
from (
SELECT er.email, COUNT(fd.Decision) AS CountDecision
, max(COUNT(fd.Decision)) over() maxCountDecision
FROM EmailReferences AS er
JOIN FinalDecision AS fd ON er.ApplicationID = fd.ApplicationID
WHERE fd.Decision = 'Accepted'
GROUP BY er.email
) d
where CountDecision = maxCountDecision
email | CountDecision
:------------- | ------------:
ref10#test.org | 2
dbfiddle here

SELECT data based on result of previous row in table

I have a database of students.
CREATE TABLE classlist
(`id` int, `studentid` int, `subjectid` int, `presentid` int)
;
CREATE TABLE student
(`id` int, `name` varchar(4))
;
CREATE TABLE subject
(`id` int, `name` varchar(4))
;
CREATE TABLE classStatus
(`id` int, `name` varchar(8))
;
INSERT INTO classlist
(`id`, `studentid`, `subjectid`, `presentid`)
VALUES
(1, 111, 1, 1),
(2, 222, 3, 0),
(3, 333, 2, 1),
(4, 111, 4, 1),
(5, 111, 1, 0),
(6, 222, 3, 0),
(7, 333, 2, 1),
(8, 111, 4, 1),
(9, 111, 2, 0),
(10, 111, 4, 1),
(11, 111, 1, 1),
(12, 333, 3, 1),
(13, 333, 2, 1),
(14, 333, 3, 1)
;
INSERT INTO student
(`id`, `name`)
VALUES
(111, 'John'),
(222, 'Kate'),
(333, 'Matt')
;
INSERT INTO subject
(`id`, `name`)
VALUES
(1, 'MATH'),
(2, 'ENG'),
(3, 'SCI'),
(4, 'GEO')
;
INSERT INTO classStatus
(`id`, `name`)
VALUES
(0, 'Absent'),
(1, 'Present')
;
And I have a query which shows how many times they have been present or absent.
SELECT
studentid,
students.name AS NAME,
SUM(presentid = 1) AS present,
SUM(presentid = 0) AS absent
FROM classlist
INNER JOIN student as students ON classlist.studentid=students.id
GROUP BY studentid, NAME
See this fiddle below.
http://sqlfiddle.com/#!2/fe0b0/1
There seems to be a trend from looking at this sample data that after someone attends subjectid 4 they are often not coming to the next class. How can I capture this in a query. I want to ONLY show data WHERE last subjectid =4. So in my sample data rows matching my criteria would be.
(5, 111, 1, 0),
(9, 111, 2, 0),
(11, 111, 1, 1),
as these rows are all the next row of a studentid who had a subjectid=4.
My output would be
| STUDENTID | NAME | PRESENT | ABSENT|
| 111 | John | 1 | 2 |
To get the next class for a student, use a correlated subquery:
select cl.*,
(select min(cl2.id) from classlist cl2 where cl2.studentid = cl.studentid and cl2.id > cl.id) as nextcl
from classlist cl
Plugging this into your query example tell you you who is present and absent for the next class:
SELECT students.id, students.name AS NAME,
SUM(cl.presentid = 1) AS present, SUM(cl.presentid = 0) AS absent,
sum(clnext.presentid = 1) as presentnext
FROM (select cl.*,
(select min(cl2.id) from classlist cl2 where cl2.studentid = cl.studentid and cl2.id > cl.id) as nextcl
from classlist cl
) cl INNER JOIN
student as students
ON cl.studentid = students.id left outer join
classlist clnext
on cl.nextcl = clnext.id
GROUP BY students.id, students.NAME
Add a where cl.subjectid = 4 to get the answer for subject 4.
I fixed the query. The SQLFiddle is k.
A quick and dirty solution could be to get the Classlist.Id for all lines where subjectid=4 (let's call them n) then select all the lines where Id = n+1