sql query to joint a data table with different data from another - mysql

it is hard to explain and my english doesn't help, but there it is:
I have two data tables: "nodes" and "records".
In the nodes table I save data of questions and data of answers
nodes:
| id | name | type |
records:
| id | questionid | answerid |
I've tried albeit unsuccessfully, to make an sql query to gave me the data of all records but with the name of the answer and question intead of the id.
In short, what I need is: records.id, nodes.name (question) , nodes.name (answer)

SELECT
questions.name AS questionname
answers.name AS answername
FROM records
INNER JOIN nodes AS questions ON records.questionid=questions.id
INNER JOIN nodes AS answers ON records.answerid=answers.id

You can use this query:
SELECT q.name AS question, a.name AS answer
FROM records r
LEFT JOIN nodes q ON q.id = r.questionid
LEFT JOIN nodes a ON a.id = r.answerid
WHERE 1
For this query I build schema below:
CREATE TABLE nodes (
id int auto_increment primary key,
name varchar(30),
type int(1));
INSERT INTO nodes (name, type) VALUES
('Is it a question 01', 0),
('Is it a question 02', 0),
('This is an answer 01', 1),
('This is an answer 02', 1),
('This is an answer 03', 1);
CREATE TABLE records (
id int auto_increment primary key,
questionid int(11),
answerid int(11));
INSERT INTO records (questionid, answerid) VALUES
(1, 3), (1, 4), (1, 5), (2, 4), (2, 5);
SQL Fiddle: http://sqlfiddle.com/#!2/bfd340/1

Related

MySQL query parameters in a table field

Good afternoon.
I have two tables:
1 - table1 - (id, address, who_lives) who_lives field - text, comma-separated list of identifiers
2 - table2 - (id, name_of_resident)
composition of table 1
12| US Oregon | 12,13
14| US Washington| 9,11
composition of table 2
9 |Petrov
11|Sidorov
12|Ivanov
13|Popov
How to make MySQL request, preferably via join, that the result was
US Oregon |Ivanov,Popov
US Washington|Petrov,Sidorov
If possible, replace the comma with the br tag: Ivanov,Popov -> Ivanov >br< Popov
SELECT table1.address, GROUP_CONCAT(table2.name_of_resident SEPARATOR '<br>')
FROM table1
JOIN table2 ON FIND_IN_SET(table2.id, table1.who_lives)
GROUP BY table1.address
DEMO
That is not how you design tables. Don't do comma separated listes. Do either a (foreign) key from table 2 to table 1, or a table with table1.id and table2.id for each relation.
Then writing the query will be easier.
create table state (
state_id int primary key,
address varchar(255)
);
create table resident (
resident_id int primary key,
name varchar(255)
);
create table who_lives (
state_id int,
resident_id int,
primary key (state_id, resident_id)
);
insert into state values (12, 'US Oregon');
insert into state values (14, 'US Washington');
insert into resident values (9, 'Petrov');
insert into resident values (11, 'Sidorov');
insert into resident values (12, 'Ivanov');
insert into resident values (13, 'Popov');
insert into who_lives values (12, 12);
insert into who_lives values (12, 13);
insert into who_lives values (14, 9);
insert into who_lives values (14, 11);
select address, group_concat(name)
from state
join who_lives using (state_id)
join resident using (resident_id)
group by state_id;
http://sqlfiddle.com/#!9/e7041f/2

Sort the table by c_criticality field in sql query

i have one field wonum,C_criticality in workorder.
In C_criticality field have three option
critical
non-critical
tools
4.null or empty
In that C_criticality field some columns are null(empty) that should come at last.
Now i have to get the output in sorting order by criticality , noncritical ,tool , null value(empty value ) will come.
CREATE TABLE workorder
(
wonum int,
C_criticality varchar(255),
);
INSERT INTO workorder (wonum,C_criticality)
VALUES (2, 'critical');
INSERT INTO workorder (wonum,C_criticality)
VALUES (1, 'non-critical');
INSERT INTO workorder (wonum,C_criticality)
VALUES (15, 'critical');
INSERT INTO workorder (wonum,C_criticality)
VALUES (12, 'tool');
INSERT INTO workorder (wonum,C_criticality)
VALUES (21, 'non-critical');
INSERT INTO workorder (wonum,C_criticality)
VALUES (11, '');
output:-
C_criticality wonum
critical 2
critical 15
non-critical 21
tool 12
null 11
We can try a two-tiered sort using ISNULL and FIELD:
SELECT *
FROM yourTable
ORDER BY
ISNULL(C_criticality), -- 0 for non NULL, 1 for NULL
FIELD(C_criticality, 'criticality', 'noncritical', 'tool');
The call to FIELD will order according to the list you provided.
This works for all SQL engines, not just in MySQL
select *
from workorder
order by case when C_criticality = 'critical' then 1
when C_criticality = 'non-critical' then 2
when C_criticality = 'tools' then 3
else 4
end
Since you have tagged mysql the query would be something like ,
SELECT * FROM workorder ORDER BY FIELD(C_criticality ,'critical','non-critical','tools','null');
It depends from DBMS. In some there are options NULLS FIRST, NULLS LAST
In MySQL you can find this article interesting https://www.designcise.com/web/tutorial/how-to-order-null-values-first-or-last-in-mysql

MYSQL: select from many-to-many linking table

I have 3 tables:
1) exercise: exercise_id, name
2) equipment: equipment_id, name
3) exercise_equipment: exercise_id, equipment_id - this is the linking table between exercise and equipment. In this table, one exercise can require multiple pieces of equipment, and the same equipment can be used for many exercises.
CREATE TABLE exercise
(`ex_id` int, `name` varchar(30))
;
INSERT INTO exercise
(`ex_id`, `name`)
VALUES
(1, 'push ups'),
(2, 'sit ups'),
(3, 'squats'),
(4, 'push ups with a fitness ball')
;
CREATE TABLE equipment
(`eq_id` int, `name` varchar(30))
;
INSERT INTO equipment
(`eq_id`, `name`)
VALUES
(1, 'none'),
(2, 'mat'),
(3, 'ball')
;
CREATE TABLE exercise_equipment
(`ex_id` int, `eq_id` int)
;
INSERT INTO exercise_equipment
(`ex_id`, `eq_id`)
VALUES
(1, 2),
(2, 2),
(3, 1),
(4, 2),
(4, 3)
;
What I need to do is select all the exercises that the user can do with the equipment that he has (for example, 1 and 2 - no equipment or mat).
I have found some examples and tried the following queries with inner join and where in:
SELECT ex.ex_id, ex.name from exercise ex
LEFT JOIN exercise_equipment exeq ON ex.ex_id = exeq.ex_id
WHERE exeq.eq_id IN (1,2);
and
select ex_id, name from exercise
where ex_id in (select ex_id from exercise_equipment where eq_id in (1,2));
But they return all exercises, instead of just the first three. In this case, if the user wants to do exercises that require no equipment or a mat (1 and 2), I want push ups, sit ups, and squats to be returned, but not the mat exercise with a ball.
I hope my explanation is clear. I would really appreciate any help I can get!
You want exercises that use only 1 and 2. When you use a WHERE clause, you are filtering out all the other equipment, so that won't work.
Instead, you need to aggregate and check that no other equipment is being used for the entire exercise. This is a similar query, with a HAVING clause:
SELECT ex.ex_id, ex.name
FROM exercise ex LEFT JOIN
exercise_equipment exeq
ON ex.ex_id = exeq.ex_id
GROUP BY ex.ex_id, ex.name
HAVING SUM(exeq.eq_id NOT IN (1, 2)) = 0;
In the event that some exercises have no equipment at all, you might want:
HAVING COALESCE(SUM(exeq.eq_id NOT IN (1, 2)), 0) = 0;

Use one primary key as two foreign key in two different tables

My requirement is to make ManytoMany relation between provinces-languages and cities-languages.
So i did like this
Provinces
PK:id,
name
Languages
PK:id,
name
Provinces_Languages
province_id
languages_id
Similarly for cities:
Cities
PK:id,
name
Using same Languages Table
Cities_Languages
cities_id
languages_id
Now , i want to make oneToMany/ManytoOne relation between provinces and cities
Provinces
PK:id,
name
Cities
PK:id,
name
Here i have problem in understanding that how i connect both of them?
because provinces "id" is already used by the Provinces_Languages as foreign key.
and Cities "id" is also used by the Cities_Languages as foreign key
Please guide me how i link up these entities?
There is no problem there - add provinces_id to your Cities table and make it a foreign key for Provinces.id.
You actually could combine the Provinces_Languages and Cities_Languages tables into one. Just need to add a type field. See the below example (SQL Fiddle):
CREATE TABLE Provinces(id int auto_increment primary key,
name varchar(100));
CREATE TABLE Cities(id int auto_increment primary key,
name varchar(100),
prov_id int);
CREATE TABLE Languages(id int auto_increment primary key,
name varchar(100));
CREATE TABLE ProvCity_Languages(provcity_id int,
languages_id int,
type varchar(10));
INSERT INTO Provinces (name) VALUES
('Province1'),('Province2');
INSERT INTO Cities (name, prov_id) VALUES
('City1', 1),('City2', 1),('City3', 2),('City4', 2);
INSERT INTO Languages (name) VALUES
('English'),('Spanish'),('French'),
('Chinese'),('Pig Latin');
INSERT INTO ProvCity_Languages
(provcity_id, languages_id, type) VALUES
(1, 1, 1),(1, 2, 1),(2, 1, 1),(1, 4, 2),
(2, 1, 2),(3, 1, 2),(3, 2, 2),(4, 5, 2),
(4, 4, 2),(4, 3, 2);
SELECT p.name AS ProvName, c.name AS CityName,
GROUP_CONCAT(DISTINCT pll.name SEPARATOR ', ') AS ProvLang,
GROUP_CONCAT(DISTINCT cll.name SEPARATOR ', ') AS CityLang
FROM Provinces p
JOIN Cities c on p.id = c.prov_id
JOIN ProvCity_Languages pl on p.id = pl.provcity_id AND pl.type = 1
JOIN Languages pll on pl.languages_id = pll.id
JOIN ProvCity_Languages cl on c.id = cl.provcity_id AND cl.type = 2
JOIN Languages cll on cl.languages_id = cll.id
GROUP BY p.name, c.name
I showed the above SELECT query just to show you that you can do whatever you want with the results. The result would be something like the following:

How to get this table in MySQL?

I have the following schema:
And I want to generate a table with 3 columns - tag's name, thread's name, answers count.
Example:
Foo bar 5
Foo something 6
Foo2 somethingElse 3
What's more, there's a table "priority_threads" (1:1 with threads). I want to display only those priority threads in this table.
How can I do this? I have absolutely no idea how to even start. The only thing I did is:
SELECT tag.name, thread.title, COUNT(answer.id_answer)
FROM tag, thread, answer
WHERE thread.id_tag = tag.id_tag
AND answer.id_thread = thread.id_thread
AND thread.id_thread = priority_threads.id_thread
GROUP BY tag.name, thread.title
ORDER BY tag.name;
However using this query all values in the answer's count column are the same - count(*) from Answer table...
Try this:
SELECT tag.name, thread.title, COUNT(answer.id_answer)
FROM tag
JOIN thread ON
tag.id_tag=thread.id_tag
JOIN answer ON
thread.id_thread = answer.id_thread
JOIN priority_threads
ON thread.id_thread = priority_threads.id_thread
GROUP BY tag.name, thread.title
ORDER BY tag.name;
Here is a SQLfiddle link to the query to test it out;
Sample code:
CREATE TABLE Tag
(
id_tag int auto_increment primary key,
name varchar(20)
);
INSERT INTO Tag
(name)
VALUES
('Foo'),
('Foo2');
CREATE TABLE Thread
(
id_thread int auto_increment primary key,
id_tag int,
title varchar(20)
);
INSERT INTO Thread
(id_tag, title)
VALUES
(1,'Bar'),
(1,'Something'),
(2,'SomethingElse');
CREATE TABLE Answer
(
id_answer int auto_increment primary key,
id_thread int,
text varchar(200)
);
INSERT INTO Answer
(id_thread, text)
VALUES
(1,'jlkjalkjl'),
(1,'ioioixhakjjkj'),
(1, 'jjalkjijkajk'),
(1, 'jjalkjijkajk'),
(1, 'jjalkjijkajk'),
(2, 'jjalkjijkajk'),
(2, 'jjalkjijkajk'),
(2, 'jjalkjijkajk'),
(2, 'qqweeweraata'),
(2, 'jjalkjijkajk'),
(2, 'jjalkjijkajk'),
(3, 'popoapopop'),
(3, 'zkkasjkljz'),
(3, 'jjalkjijkajk')
;
CREATE TABLE priority_threads
(
id_priority_threads int auto_increment primary key,
id_thread int,
priority int
);
INSERT INTO priority_threads
(id_thread, priority)
VALUES
(1,1),
(3,2);
so:
SELECT tag.name, thread.title, COUNT(answer.id_answer)
FROM tag, thread, answer
WHERE thread.id_tag = tag.id_tag
AND answer.id_thread = thread.id_thread
GROUP BY tag.name, thread.title
ORDER BY tag.name;
can look like this:
SELECT tag.name, thread.title, COUNT(answer.id_answer)
FROM tag
JOIN thread ON
tag.id_tag=thread.id_tag
JOIN answer ON
thread.id_thread = answer.id_thread
GROUP BY tag.name, thread.title
ORDER BY tag.name;
The results are the same, the former is preferred by most. Okay, but I think the real issue here is this line here in your posted code:
AND thread.id_thread = priority_threads.id_thread
you are referencing another table, priority_threads, which is not in your query. Either add the join or remove it and you should be good to go.
-james