mysql update statement using 3 tables - mysql

I am developing a database on online quiz management
one table stdinfo stores usernames and student details
table testinfo stores the testid name subjects and their marking schemes(separate for each subject) in form of multiple rows like
and one table question has all the questions with their qids
and one table records the responses of students
Now there is a column marks in responses which displays the marks obtained in that question.
Since i want to generate the result i have already inserted the responses and their ids/usernames. Now i want to insert marks for calculate result;
what it should do
set marks=0 where the response is null ;
set marks=posmark obtained from the testinfo table for respective subject if the response is correct
set marks=negmark obtained from the testinfo table for respective subject if the response is incorrect
table structures are given below;

I'm reposting the answer in a more elaborate manner since my prevoius answer was deleted.
I found it myself and also found the answer by #Jirka49 helpful. See link below.
See the last section in the webpage
So, we need to avoid the use of the IN operator.
So create a temporary table during the query which contains details of the questions,test information and question information(the positive marks) wherever the student has answered correctly.
Now use this table to update the responses table by where clause.
So the query becomes:
update responses,
(select posmark,responses.testid,responses.qid,responses.stid from testinfo,responses,question
where testinfo.testid=responses.testid and responses.testid="<whatever testid>" and question.qid=responses.qid and question.cans=responses.response and question.subcode=testinfo.subcode and responses.stid='<for whichever student>')as temp
set responses.marks=temp.posmark where responses.qid=temp.qid and temp.testid=responses.testid and responses.stid=temp.stid;
Similar thing can be done for negative marks too. And check wheverever answers are null a simple query will assign zero marks.

see the answer for your question [here][1] https://forums.mysql.com/read.php?20,85813,85816#msg-85816
or look at this:
UPDATE a
INNER JOIN b USING (id)
SET a.firstname='Pekka', a.lastname='Kuronen',
b.companyname='Suomi Oy',companyaddress='Mannerheimtie 123, Helsinki Suomi'
WHERE a.id=1;

Related

Having trouble getting values when creating new table [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
Fairly new to SQL - Using MySQL with PhpMyAdmin - I have two CSV sheets that have information that need to be merged into a new CSV while removing all other inapplicable columns. The columns I need are email, user_id, and need to create a new column titled "role"
The email column is different on each file, and the end result would be 74 lines, not 100 (not all emails will match). So far, I've been able to use join to get the columns I need. What I'm struggling with is creating a new table with "role" and having the data transfer over.
The table is created, with the right columns, but the values from example and test do not appear.
What I started with:
Select example.user_name,
test.email
from example
join test
on example.user_email = test.email
Where I got to:
CREATE table test2 (role text)
select email, user_name
from (
Select example.user_name,test.email
from example
join test
on example.user_email = test.email)
As Test
I've been at this for 4 hours (took me a good chunk of time just to get to this point) and this hurdle has been the most difficult. Any help would be greatly appreciated!
Table 1 Example.
User ID :1111.
User_email: example.com.
Table 2 Test
first_name: Tom
last_name: Laugh.
email: example.com
The first query joins these two together. The third table would need to add "role" which would be a defined value and would look like
Table 3 All together.
Role: onboarding.
user_id: 1111.
user_email: example.com
Hope that helps clarify things! Apologies for the confusion.
CREATE TABLE test2 ( user_email VARCHAR(255),
user_id INT PRIMARY KEY,
user_name VARCHAR(255),
role TEXT)
SELECT user_email,
example.user_id,
CONCAT_WS(' ', test.first_name, test.last_name) user_name,
'onboarding' role
FROM example
JOIN test USING (user_email);
Specify new table structure completely. This eliminates some possible problems in future (for example, you may obtain string columns which are shorter than you need).
Specify column names in SELECT part completely with strict matching to those in table definition - if not then destination columns would be empty but excess columns with unneeded (and sometimes strange) names will be added.
Always use absolutely the same names for matching columns in different tables until it is impossible.
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=5e7c77aa8ad2f5f44e1851bd3ebe17e7

mysql query using column values as parameter in query phpMyAdmin

I have a query i have been working on trying to get a specific set of data, join the comments in duplicate phone numbers of said data, then join separate tables based on a common field "entry_id" which also happens to be the number on the end of the word custom_ to pull up that table.
table named list and tables containing the values i want to join is custom_entry_id (with entry_id being a field in list in which i need the values of each record to replace the words in order to pull up that specific table) i need entry_id from the beginning part of my query to stick onto the end of the word custom for every value my search returns to get the fields from that custom table designated for that record. so it will have to do some sort of loop i guess? sorry like i said I am at a loss at this point
this is where i am so far:
SELECT * ,
group_concat(comments SEPARATOR '\r\n\r\n') AS comments_combined
FROM list WHERE `status` IN ("SALEA","SALE")
GROUP BY phone_number
//entry_id is included in the * as well as status
// group concat combines the comments if numbers are same
i have also experimented on test data with doing a full outer join which doesnt really exist. i feel if you can solve the other part for me i can do the joining of the data with a query similar to this.
SELECT * FROM test
LEFT JOIN custom_sally ON test.num = custom_sally.num
UNION
SELECT * FROM test
RIGHT JOIN custom_sally ON test.num = custom_sally.num
i would like all of this to appear with every field from my list table in addition to all the fields in the custom_'entry_id' tables for each specific record. I am ok with values being null for records that have different custom fields. so if record 1 has custom fields after the join of hats and trousers and record 2 has socks and shoes i realize that socks and shoes for record 1 will be null and hats and trousers for record 2 will be null.
i am doing all this in phpmyadmin under the SQL tab.
if that is a mistake please advise as well. i am using it because ive only been working with SQl for a few months. from what i read its the rookie tool.
i might be going about this all wrong if so please advise
an example
i query list with my query i get 20,000 rows with columns like status, phone_number, comments, entry_id, name, address, so on.
now i want to join this query with custom fields in another table.
the problem is the custom tables' names are all linked to the entry_id.
so if entry_id is 777 then the custom table fields are custom_777
my database has over 100 custom tables with specials fields for each record depending on its entry_id.
when i query the records I don't know how to join the custom fields that are entry_id specific to the rest of my data.i will pull up some tables and data for a better example
this is the list table:
this is the custom_"entry_id"
Full Outer Join in MySQL
for info on full outer joins.

Finding duplicate records by searching a few characters

I know there are many questions answered under this title. But I believe I have a unique situation where I need a specific way to find and export the duplicate data from my database.
I have a database with over 20.000 contacts. I need a query to find duplicate records in the contacts table. But since there are many same last names, or first names for different people, I want to lookup the first few characters of the first name and the last name to see if there is a duplicate record matching the query.
So, the query could be explained like this: Look at the first two characters from the firstName column, then look at the first three characters from the lastName column, and show it with any similar records.
I would highly appreciate any advice. Thank you.
Here's how I'd do it, assuming your contacts table is called contacts:
select *
from contacts c
join contacts c2 on c2.id!=c.id
and left(c2.firstName,2)=left(c.firstName,2)
and left(c2.lastName,3)=left(c.lastName,3)

Creating a complicated MySQL Update Query

I am trying to create an UPDATE query that will replace the NameID field on a table called TimeStamps with the user's id field value from another table called Names. Here is some sample data.
Names Table
id:1
name:John
password:1234
TimeStamps Table
id:1
name:**John**
timestamp:01/01/2000 12:00:00
I want to replace the Name field in the TimeStamps table with the corresponding id value from the Names table. I'm not entirely sure on how to write the query but I know it starts with something like this.
UPDATE TimeStamps
SET NameID=(NamesTableReference)
WHERE NameID=(TimeStampsTableReference);
This way I can start to run queries against the user's id and not the user's Name. We have more than one user with the same name and it doesn't pull the right data because it is pulling multiple users. I can update the data manually but there are several hundred thousand rows in the table and that would take entirely too much time. Can anyone shed some light on what I need to add/change in the query below? Thanks!
I think you just want a join:
update timestamps t join
names n
on t.id = n.id
set t.name = n.name;
However, the update shouldn't be necessary. You have an id connecting the two tables. Just use it when you are using timestamps. That is, use a join to look up the name rather than storing it in both places -- and running the risk that the names associated with an id somehow end up different in the two tables.
It looks like this query did the trick.
UPDATE TimeStamps t, Names n
SET t.NameID = n.id
WHERE t.NameID = n.Name
Thanks everyone for your input and your help! Hope this can help someone else in the future!

The optimal way to store multiple-selection survey answers in a database

I'm currently working on a survey creation/administration web application with PHP/MySQL. I have gone through several revisions of the database tables, and I once again find that I may need to rethink the storage of a certain type of answer.
Right now, I have a table that looks like this:
survey_answers
id PK
eid
sesid
intvalue Nullable
charvalue Nullable
id = unique value assigned to each row
eid = Survey question that this answer is in reply to
sesid = The survey 'session' (information about the time and date of a survey take) id
intvalue = The value of the answer if it is a numerical value
charvalue = the value of the answer if it is a textual representation
This allowed me to continue using MySQL's mathematical functions to speed up processing.
I have however found a new challenge: storing questions that have multiple responses.
An example would be:
Which of the following do you enjoy eating? (choose all the apply)
Girl Scout Cookies
Bacon
Corn
Whale Fat
Now, when I want to store the result, I'm not sure of the best way to handle it.
Currently, I have a table just for multiple choice options that looks like this:
survey_element_options
id PK
eid
value
id = unique value associated with each row
eid = question/element that this option is associated with
value = textual value of that option
With this setup, I then store my returned multiple selection answers in 'survey_answers' as strings of comma separated id's of the element_options rows that were selected in the survey. (ie something like "4,6,7,9") I'm wondering if that is indeed the best solution, or if it would be more practical to create a new table that would hold each answer chosen, and then reference back to a given answer row which in turn references back to the element and ultimately the survey.
EDIT
for anyone interested, here is the approach I ended up taking (In PhpMyAdmin Relations View):
And a rudimentary query to gather the counts for a multiple select question would look like this:
SELECT e.question AS question, eo.value AS value, COUNT(eo.value) AS count
FROM survey_elements e, survey_element_options eo, survey_answer_options ao
WHERE e.id = 19
AND eo.eid = e.id
AND ao.oid = eo.id
GROUP BY eo.value
This really depends on a lot of things.
Generally, storing lists of comma separated values in a database is bad, especially if you plan to do anything remotely intelligent with that data. Especially if you want to do any kind of advanced reporting on the answers.
The best relational way to store this is to also define the answers in a second table and then link them to the users response to a question in a third table (with multiple entries per user-question, or possibly user-survey-question if the user could take multiple surveys with the same question on it.
This can get slightly complex as a a possible scenario as a simple example:
Example tables:
Users (Username, UserID)
Questions (qID, QuestionsText)
Answers (AnswerText [in this case example could be reusable, but this does cause an extra layer of complexity as well], aID)
Question_Answers ([Available answers for this question, multiple entries per question] qaID, qID, aID),
UserQuestionAnswers (qaID, uID)
Note: Meant as an example, not a recommendation
Convert primary key to not unique index and add answers for the same question under the same id.
For example.
id | eid | sesid | intval | charval
3 45 30 2
3 45 30 4
You can still add another column for regular unique PK if needed.
Keep things simple. No need for relation here.
It's a horses for courses thing really.
You can store as a comma separated string (But then what happens when you have a literal comma in one of your answers).
You can store as a one-to-many table, such as:
survey_element_answers
id PK
survey_answers_id FK
intvalue Nullable
charvalue Nullable
And then loop over that table. If you picked one answer, it would create one row in this table. If you pick two answers, it will create two rows in this table, etc. Then you would remove the intvalue and charvalue from the survey_answers table.
Another choice, since you're already storing the element options in their own table, is to create a many-to-many table, such as:
survey_element_answers
id PK
survey_answers_id FK
survey_element_options_id FK
Again, one row per option selected.
Another option yet again is to store a bitmask value. This will remove the need for a many-to-many table.
survey_element_options
id PK
eid FK
value Text
optionnumber unique for each eid
optionbitmask 2 ^ optionnumber
optionnumber should be unique for each eid, and increment starting with one. There will impose a limit of 63 options if you are using bigint, or 31 options if you are using int.
And then in your survey_answers
id PK
eid
sesid
answerbitmask bigint
Answerbitmask is calculated by adding all of the optionbitmask's together, for each option the user selected. For example, if 7 were stored in Answerbitmask, then that means that the user selected the first three options.
Joins can be done by:
WHERE survey_answers.answerbitmask & survey_element_options.optionbitmask > 0
So yeah, there's a few options to consider.
If you don't use the id as a foreign key in another query, or if you can query results using the sesid, try a many to one relationship.
Otherwise I'd store multiple choice answers as a serialized array, such as JSON or through php's serialize() function.