I have three tables as shown below. The topics_table is to be created by inserting values from grades_table and subjects_table and a few other fields that are either taken in as input(topic_name) or calculated(revision dates).
grades_table
grade_id
grades
sections
1
1
A
2
1
B
subjects_table
subject_id
grade_id
teacher_id
subject_name
1
1
1
Maths
2
2
2
English
topics_table (NOTE: this table is currently empty).
I want to add values of grade_id and subject_id from the grades and subjects table to this table. Basically, I am thinking of joining the subject table and grades table and extracting the required values from that and put it in this table under grade id and subject id columns while also putting in topic_name from the user and revision dates from the system.
topic_id
grade_id
subject_id
topic_name
revision_one
revision_two
revision_three
1
1
1
Adding Fractions
28-10-2021
28-11-2021
28-12-2021
2
2
2
Nouns
01-11-2021
01-12-2021
01-01-2022
Right now, I am using join to insert the values of grade_id and subject_id in the topics_table, but the issue is that I am not able to receive the topic_name and revision dates as they are extra columns that cannot be taken from another table using joins.
Below is the MySQL query that I'm using to obtain topics_table right now. It only gives grade_id and subject_id.
How do I also get the extra columns?
Note that this table will be updated each time using the same query when the input for topic_name is entered.
Here, $chooseGrade, $chooseSubject, $chooseSection are the inputs that I will be receiving from the user via a form. $teacherId is received from another table using a different query.
Let me know if there is another way of taking in values from grades table and subjects table and putting it in the topics table. I tried to use SQL variables but even that didn't work. The code for that is also given.
INSERT INTO topics_table (subject_id, grade_id, $topicName , CURRENT_DATE(),CURRENT_DATE()+INTERVAL 1 DAY,CURRENT_DATE()+INTERVAL 7 DAY,CURRENT_DATE()+INTERVAL 30 DAY,CURRENT_DATE()+INTERVAL 90 DAY,CURRENT_DATE()+ INTERVAL 180 DAY)
SELECT G.grade_id, S.subject_id
FROM grades_table G
INNER JOIN subjects_table S
WHERE G.grade_id = S.subject_id
AND G.grades = $chooseGrade
AND G.sections = $chooseSection
AND S.subject_name = $chooseSubject
AND S.teacher_id = $teacherId
//using variables NOT joins
SELECT grade_id INTO #grade_id FROM grades_table WHERE grades = '$chooseGrade' AND sections = '$chooseSection';
SELECT subject_id INTO #subject_id FROM subjects_table WHERE grade_id = #grade_id AND subject_name = '$chooseSubject' AND teacher_id = '$teacherId';
INSERT INTO topics_table ( subject_id, grade_id, topic_name, revision_one, revision_two, revision_three) VALUES (#subject_id, #grade_id,'$topicName',CURRENT_DATE()+INTERVAL 30 DAY,CURRENT_DATE()+INTERVAL 60 DAY,CURRENT_DATE()+ INTERVAL 90 DAY);
you will have noticed that i replaced the variable with placeholders
See pleasr this topic about sql injection
Another thing is you joining form your query doesn't seem that correct to me, because Grades and subject should be referenced by grades_id and not be subject_id
the same goes for topics_table grades_id, seems also redundant, so you should take a look at normalisation
SELECT G.grade_id, S.subject_id,t.topic_name,t.revision_one, t.revision_two , t.revision_three
FROM grades_table G
INNER JOIN subjects_table S ON G.grade_id = S.grade_id
INNER JOIN topics_table t ON t.grade_id = s.grade_id AND t.subject_id = s.subject_id
WHERE G.grades = ?
AND G.sections = ?
AND S.subject_name = ?
AND S.teacher_id = ?
You should use merge if you want to get a single table as output
MERGE Subject S
USING Grade G
ON (S.SubjectID = G.GradeID)
WHEN MATCHED
THEN UPDATE SET
COLUMNAME = COLUMNNAME,
COLUMNNAME = COLUMNANAME
WHEN NOT MATCHED BY TARGET
THEN INSERT (XYZ, ABC, ABZ)
VALUES(XYZ,ABC,ABZ)
WHEN NOT MATCHED BY SOURCE
THEN DELETE
note: use your own values in place of xyz,abc etc
Related
I want to get data from two tables in my DB. Here's what my tables might look like:
subject_code: semester, subjectcode, subjectname
markmanagment: subjectcode, semester, marks, rollno
i want to select rollno value=1 and semester value=1 and its corresponding values of marks and subject code from table markmanagment and for the same value of semester and subject code i want the subjectname from subject_code
This is a very basic join. Use an INNER JOIN to see only the results that have records in both tables - I used the subject code in the ON statement but you could also use semester here. Then specify your other conditions in the WHERE clause. In your SELECT statement, specify the columns you want to see returned by listing them in the following format: tablename.columnname. I use * here to return all columns.
SELECT *
FROM subject_code sc
INNER JOIN markmanagement mm ON sc.subjectcode = mm.subjectcode
WHERE sc.semester = mm.semester
AND sc.semester = 1
AND mm.rollno = 1
You should do a join table (Inner - Right - Left or Full, depending on your table).
Like :
SELECT * FROM subject_code
INNER JOIN markmanagment
ON subject_code.subjectcode = markmanagment.subjectcode;
WHERE markmanagment.rollno = 1 AND subject_code.semester = 1
You can specify multiple conditions in the on part of a join. For example:
select *
from markmanagement mm
join subject_code sc
on mm.subjectcode = sc.subjectcode
and mm.semester = sc.semester
where mm.semester = 1
and mm.rollno = 1
Hoping, i understood your problem correctly.
Tried to create same problem.
Sqlfiddle link - http://sqlfiddle.com/#!9/5a074b/2/0
create table subject_code
(
semester int,
subjectcode varchar(100),
subjectname varchar(100)
);
insert into subject_code values(1,'S01','subject1');
insert into subject_code values(1,'S02','subject2');
insert into subject_code values(2,'S01','subject1');
create table markmanagment
(
subjectcode varchar(100),
semester int,
marks int ,
rollno int
);
insert into markmanagment values('S01',1,75,1);
insert into markmanagment values('S02',1,80,1);
insert into markmanagment values('S01',2,85,1);
I think below query will help
select b.marks , b.subjectcode , a.subjectname
from subject_code a, markmanagment b
where a.semester = b.semester
and a.subjectcode = b.subjectcode
and a.semester = 1
and b.rollno = 1;
I have three tables in mySQL:
TABLE:CollectionAttributeValues
cID
akID
avID
TABLE: atDefault
avID
value
TABLE: CollectionVersions
cID
cvName
Looks Like
CollectionVersions
cID cvName
1 Billete
5 Tony
atDefault
avID value
1 B.B
3 T.T
CollectionAttributeValues
cID akID avID
1 29 1
5 29 3
I need to take all the values (the column named values) in atDefault"
and put it into cvName in CollectionVersions
WHERE akID = 29 in CollectionAttributeValues
Basically, take "Billette" and change it to "B.B". AND also take "Tony" and change it to "TT".
So far I came up with this
SELECT value
FROM `atDefault` AS d
LEFT JOIN `CollectionAttributeValues` AS v ON d.avID = v.avID
WHERE v.akID =29
But I don't know how to insert the resulting values into the "cvName" column in CollectionVersions...
To UPDATE all the columns of the table CollectionVersions with the data that you get form the query. Try the below query -
UPDATE CollectionVersions cv
SET cvName =
(SELECT value
FROM `atDefault` AS d
LEFT JOIN `CollectionAttributeValues` AS v ON d.avID = v.avID
WHERE v.akID =29
AND cv.cID = v.cID)
I have this data in a table, for instance,
id name parent parent_id
1 add self 100
2 manage null 100
3 add 10 200
4 manage null 200
5 add 20 300
6 manage null 300
How can I left join or inner join this table itself so I get this result below?
id name parent
2 manage self
4 manage 10
6 manage 20
As you can I that I just want to query the row with the keyword of 'manage' but I want the column parent's data in add's row as the as in manage's row in the result.
Is it possible?
EDIT:
the simplified version of my actual table - system,
system_id parent_id type function_name name main_parent make_accessible sort
31 30 left main Main NULL 0 1
32 31 left page_main_add Add self 0 1
33 31 left page_main_manage Manage NULL 0 2
my actual query and it is quite messy already...
SELECT
a.system_id,
a.main_parent,
b.name,
b.make_accessible,
b.sort
FROM system AS a
INNER JOIN -- self --
(
SELECT system_id, name, make_accessible, sort
FROM system AS s2
LEFT JOIN -- search --
(
SELECT system_id AS parent_id
FROM system AS s1
WHERE s1.function_name = 'page'
) AS s1
ON s1.parent_id = s2.parent_id
WHERE s2.parent_id = s1.parent_id
AND s2.system_id != s1.parent_id
ORDER BY s2.sort ASC
) b
ON b.system_id = a.parent_id
WHERE a.function_name LIKE '%manage%'
ORDER BY b.sort ASC
result I get currently,
system_id main_parent name make_accessible sort
33 NULL Main 0 1
but I am after this,
system_id main_parent name make_accessible sort
33 self Main 0 1
You just need to reference the table twice:
select t1.id, t1.name, t2.id, t2.name
from TableA t1
inner join TableA t2
on t1.parent_id = t2.Id
Replace inner with left join if you want to see roots in the list.
UPDATE:
I misread your question. It seems to me that you always have two rows, manage one and add one. To get to "Add" from manage:
select system.*, (select parent
from system s2
where s2.parent_id = system.parent_id
and s2.name = 'add')
AS parent
from system
where name = 'manage'
Or, you might split the table into two derived tables and join them by parent_id:
select *
from system
inner join
(
select * from system where name = 'add'
) s2
on system.parent_id = s2.parent_id
where system.name = 'manage'
This will allow you to use all the columns from s2.
Your data does not abide to a child-parent hierarchical structure. For example, your column parent holds the value 10, which is not the value of any id, so a child-parent association is not possible.
In other words, there's nothing that relates the record 2,manage,null to the record 1,add,self, or the record 4,manage,null to 3,add,10, as you intend to do in your query.
To represent hierarchical data, you usually need a table that has a foreign key referencing it's own primary key. So your column parent must reference the column id, then you can express a child-parent relationship between manage and add. Currently, that's not possible.
UPDATED: Joining by parent_id, try:
select m.id, m.name, a.parent
from myTable m
join myTable a on m.parent_id = a.parent_id and a.name = 'add'
where m.name = 'manage'
Change the inner join to a left join if there may not be a corresponding add row.
Have seen multiple posts on this but I can't see any which answer my question.
Basically I have 3 tables in my database which relate to members and their categorisation/classification.
members (defines list of members and associated data)
member_taxonomy (defines categories, subcategories and facilities using combination of partent id and enumerated field tax_type (CATEGORY, SUBCATEGORY, FACILITY)
member_taxonomy_map (defines mapping between members and member_taxonomy)
I have a members page within which are a number of options to refine the search by specifying one or more subcategory and one or more facility. I have been trying to search on the table using the query:
SELECT members.*
FROM (members)
JOIN member_taxonomy_map ON member_taxonomy_map.member_id = members.id
WHERE member_taxonomy_map.taxonomy_id = 1
AND member_taxonomy_map.taxonomy_id = 26
AND members.active = 1
AND members.deleted = 0;
However this returns 0 rows which is something to do with having multiple where clauses on the same column but I can't figure out how this query should look. Each time the search is refined (and there could be up to 30 different options to refine the search) I need add an additional AND clause so that only members with these mappings are returned.
An IN clause will not work as this is effectively returning any rows which match any of these particular values but this is incorrect as it needs to match exactly the values specified.
Hopefully someone can give me a few pointers in the right direction.
Thanks in advance.
UPDATE
It is possible that taxonomy_id can be 1 and 26. I prob need to include the schema for the members_taxonomy_map table.
id int
tax_name varchar
slug varchar
tax_type enum ('CATEGORY','CLASSIFICATION','FACILITY','RATING')
parent_id int
active int
Therefore any tax_type with no parent id set are top level CATEGORY. Subcategories have a parent_id CATEGORY. CLASSIFICATION's can have a parent_id of the CATEGORY and FACILITY's have a parent_id of CATEGORY.
Therefore for example a category could be accommodation, sub-category could be hotel and facility could be wifi. Therefore if a member has all three of these items they will have 3 entries in the mapping table. I need to be be able to filter these so that it builds up the query to filter depending on the accommodation types (i.e subcategories - those entries with a tax_type of CATEGORY but also have a parent id, then within this the classifications. The query may return multiple entries for the same member but I can deal with this by filter these out with extra SQL clauses.
SELECT members.*
FROM (members)
JOIN member_taxonomy_map ON member_taxonomy_map.member_id = members.id
WHERE (member_taxonomy_map.taxonomy_id = 1
OR member_taxonomy_map.taxonomy_id = 26)
AND members.active = 1
AND members.deleted = 0;
It's probably not possible for a record to have a taxonomy_id of 1 and 26; you are probably trying to get a record that contains one or the other.
SELECT mb.*
FROM members mb
JOIN member_taxonomy_map tm ON tm.member_id = mb.id
WHERE tm.taxonomy_id IN ( 1, 26)
AND mb.active = 1
AND mb.deleted = 0
;
... Or ...
SELECT mb.*
FROM members mb
WHERE EXISTS ( SELECT *
FROM member_taxonomy_map tm
WHERE ON tm.member_id = mb.id
AND tm.taxonomy_id IN ( 1, 26)
)
AND mb.active = 1
AND mb.deleted = 0
;
... Or ...
SELECT mb.*
FROM members mb
WHERE mb.id IN ( SELECT tm.member_id
FROM member_taxonomy_map tm
WHERE tm.taxonomy_id IN ( 1, 26)
)
AND mb.active = 1
AND mb.deleted = 0
;
You need to JOIN member_taxonomy_map for every taxonomy_id
SELECT members.*
FROM members
JOIN member_taxonomy_map mtm1 ON mtm1.member_id = members.id AND mtm1.taxonomy_id=1
JOIN member_taxonomy_map mtm26 ON mtm26.member_id = members.id AND mtm26.taxonomy_id=26
WHERE members.active = 1
AND members.deleted = 0;
i have a details table with columns:
user_id int
code int
value int
And i want to build a summary table that looks like:
user_id int
valueA int
valueB int
In the details table, valueA would correspond to say, code 5, and valueB would correspond to say, code 6, so i'm looking for something like:
insert into summary (user_id,valueA,valueB) VALUES ( SELECT ??? from details );
The problem of course is that i'm looking at multiple rows from the "details" table to populate one row in the "summary" table.
Eg, if i had the following rows in details:
1 5 100
1 6 200
2 5 1000
2 6 2000
I want to end up with the following in the summary table:
1 100 200
2 1000 2000
Any ideas?
MySQL doesn't have PIVOT/UNPIVOT syntax, which leaves you to use a combination of GROUP BY and CASE expressions:
INSERT INTO SUMMARY
(user_id,valueA,valueB)
SELECT d.user_id,
MAX(CASE WHEN d.code = 5 THEN d.value ELSE NULL END),
MAX(CASE WHEN d.code = 6 THEN d.value ELSE NULL END),
FROM DETAILS d
GROUP BY d.user_id
insert into summary (user_id,valueA,valueB)
SELECT a.user_id, a.value, b.value
from details a
join details b on a.user_id = b.user_id
WHERE a.code = 5 and b.code = 6;
beware: you will end up with multiple summary columns if user_id+code is not unique.
EDIT:
insert into summary (user_id,valueA,valueB)
select u.user_id, ifnull(a.value,0), ifnull(b.value,0)
from (select distinct user_id from details /* where code in (5,6) */) u
left join details a on a.user_id = u.user_id and a.code = 5
left join details b on b.user_id = u.user_id and b.code = 6
If you have a manageable set of codes (say just 5 and 6) you could do something like this:
SELECT details.user_id, code5.value, code6.value
FROM details JOIN
(SELECT user_id, value FROM details WHERE code = 5) AS code5 USING(user_id)
JOIN
(SELECT user_id, value FROM details WHERE code = 6) AS code6 USING(user_id);
You may need to modify your JOINs depending on if your codes are not required as 1 to 1 relationship (i.e. LEFT JOINs).
If you have a large set of codes, I would look into a cursor runs a similar query above over a result set of your codes or using a different technology, (i.e. PHP script).