MySQL select from multiple table with conditions - mysql

I have 4 tables:
ARTICOLE
BAR
BUCATARIE
MAGAZIE
mysql> select * from ARTICOLE;
| OID | ART |
| 1 | TEST |
| 2 | TESTQ |
| 3 | MYART |
| 4 | MYARTBUC |
4 rows in set (0.00 sec)
mysql> select * from BAR;
| OID | ART | CANT |
| 1 | TEST | 3.00000 |
| 2 | TESTQ | 1.00000 |
| 3 | MYART | 20.00000 |
3 rows in set (0.00 sec)
mysql> select * from BUCATARIE;
| OID | ART | CANT |
| 1 | TEST | 5.00000 |
| 2 | MYARTBUC | 10.00000 |
2 rows in set (0.00 sec)
mysql> select * from MAGAZIE;
Empty set (0.00 sec)
the below query
mysql> select a.ART,sum(bar.CANT),sum(buc.CANT),sum(mag.CANT) from ARTICOLE a,BUCATARIE buc,BAR bar,MAGAZIE mag where a.ART=bar.ART and a.ART=bar.ART and a.ART=mag.ART group by a.ART;
return:
Empty set (0.00 sec)
how must be query to return:
| ART | sum(bar.CANT) | sum(buc.CANT) | sum(mag.CANT) |
TEST | 3.00000 | 5.00000 | NULL |
TESTQ | 1.00000 | NULL | NULL |
MYART | 20.00000 | NULL | NULL|
MYARTBUC | NULL | 10.00000 | NULL |
????
Any help appreciated.

You need to make use of LEFT JOIN to include results from other tables without filtering out records that don't match:
select a.ART,sum(bar.CANT),sum(buc.CANT),sum(mag.CANT)
from ARTICOLE a
left join BUCATARIE buc on buc.ART = a.ART
left join BAR bar on bar.ART = a.ART
left join MAGAZIE mag on mag.ART = a.ART
group by a.ART;
Sample results:
ART SUM(BAR.CANT) SUM(BUC.CANT) SUM(MAG.CANT)
MYART 20
MYARTBUC 10
TEST 3 5
TESTQ 1
Demo: http://www.sqlfiddle.com/#!2/6efb2/2

Related

Curious as to know why this doesn't work MySQL

What I'm trying to do is get every teacher name involved with the class_id provided. And it does nothing, very strange.The tables the query is connected to:
+----+------------+----------+
| id | teacher_id | class_id |
+----+------------+----------+
| 1 | 1 | 2 |
| 6 | 1 | 4 |
| 10 | 2 | 3 |
| 5 | 2 | 5 |
| 4 | 3 | 1 |
| 7 | 3 | 3 |
| 9 | 4 | 2 |
| 2 | 4 | 4 |
| 3 | 5 | 1 |
| 8 | 5 | 5 |
+----+------------+----------+
10 rows in set (0,00 sec)
mysql> select * from classes;
+----------+------------+------------------------+
| id_class | class_name | responsible_teacher_id |
+----------+------------+------------------------+
| 1 | Geography | 2 |
| 2 | Reading | 1 |
| 3 | Science | 3 |
| 4 | History | 5 |
| 5 | Arithmetic | 4 |
+----------+------------+------------------------+
5 rows in set (0,00 sec)
mysql> select * from teachers;
+----+------------+-------------+-----------+------------+------------+-------------+----------------------------------+
| id | first_name | middle_name | last_name | birthdate | subject_id | current_age | md5 |
+----+------------+-------------+-----------+------------+------------+-------------+----------------------------------+
| 1 | Oliver | Weed | Saxon | 1983-01-03 | 2 | 38 | 4bf51ce48af83dba7c8390a7222db991 |
| 2 | Dexter | Tristan | Morgan | 1980-12-11 | 5 | 40 | be96d6213828fd09538d8b1357907d54 |
| 3 | Deborah | Ocean | Morgan | 1985-06-10 | 2 | 35 | ba6869ece0a74ca9987b83b4f840405b |
| 4 | George | Kai | Smith | 1965-01-03 | 6 | 56 | ccec54863dbb6b63e55d495341fd9a63 |
| 5 | Chi | Kai | Chian | 1979-10-03 | 3 | 41 | 2291ce528bf05eff905af1eecd9bc53b |
+----+------------+-------------+-----------+------------+------------+-------------+----------------------------------+
5 rows in set (0,00 sec)
And the query:
select first_name
, middle_name
, last_name
FROM teachers_seth t
JOIN classes_sethputz c
ON c.responsible_teacher_id = t.id
JOIN teachers_classes_sethputz t_c
ON t_c.class_id = c.id_class
AND t_c.teacher_id = t.id
WHERE c.id_class = 1;
And what the query returned each time I ran it with a different class_id:
c.id_class = 1;
Empty set (0,00 sec)
c.id_class = 2;
+------------+-------------+-----------+
| first_name | middle_name | last_name |
+------------+-------------+-----------+
| Oliver | Weed | Saxon |
+------------+-------------+-----------+
1 row in set (0,00 sec)
c.id_class = 3;
+------------+-------------+-----------+
| first_name | middle_name | last_name |
+------------+-------------+-----------+
| Deborah | Ocean | Morgan |
+------------+-------------+-----------+
1 row in set (0,00 sec)
c.id_class = 4;
Empty set (0,00 sec)
c.id_class = '5';
Empty set (0,00 sec)
Thanks. This is really strange for me.
You have too much joining going on for your question, you have 3 tables, teachers, classes and a matrix that links them many-many.
You are joining the classes table directly to the teachers table with the responsible_teacher_id column, this should not be there if you want the teachers involved with the classes. What you are doing is saying if the teachers are the responsible teacher AND the teacher is involved in the class and that is rarely the case so you get very few hits.
So to solve it, start with the class table (classes_sethputz), as that is what you appear to be doing and then add in the matrix table (teachers_classes_sethputz) by joining it then add in the teachers table (teachers_seth) by joining it to the matrix table (teachers_classes_sethputz).
SELECT first_name
, middle_name
, last_name
FROM classes_sethputz c
JOIN teachers_classes_sethputz t_c
ON t_c.class_id = c.id_class
JOIN teachers_seth t
ON t.id = t_c.teacher_id
WHERE c.id_class = 5;

concat and group concat from a table that join with another table

How to use concat and group concat from a table that join with another table.
The schema looked like this :
FIRST TABLE :
MariaDB [ittresnamuda]> select * from tb_tipe_request;
+---------+------------+
| id_tipe | nama_tipe |
+---------+------------+
| 1 | Perbaikan |
| 2 | Permintaan |
+---------+------------+
2 rows in set (0.00 sec)
SECOND TABLE
MariaDB [ittresnamuda]> select a.ID_REQUEST, a.CATATAN from tb_requestfix a;
+------------+---------------------------------+
| ID_REQUEST | CATATAN |
+------------+---------------------------------+
| 3 | Akan kami cek jaringan tersebut |
| 4 | Iya, go ahead. Appproved |
| 5 | Sudah di refill |
| 28 | Saja |
+------------+---------------------------------+
4 rows in set (0.00 sec)
THIRD TABLE
MariaDB [ittresnamuda]> select * from tb_link_tipe_request;
+----+------------+---------+
| id | id_request | id_tipe |
+----+------------+---------+
| 8 | 4 | 1 |
| 9 | 4 | 2 |
| 11 | 3 | 1 |
| 12 | 5 | 2 |
| 40 | 28 | 1 |
+----+------------+---------+
5 rows in set (0.00 sec)
I already use join, concat, and group_concat, but still no result. I need to select the table like this :
+------------+---------------------------------+------------------------+
| ID_REQUEST | CATATAN | TIPE_REQUEST |
+------------+---------------------------------+------------------------+
| 3 | Akan kami cek jaringan tersebut | Perbaikan |
| 4 | Iya, go ahead. Appproved | Perbaikan / Permintaan |
| 5 | Sudah di refill | Permintaan |
| 28 | Saja | Perbaikan |
+------------+---------------------------------+------------------------+
For the help, thanks a lot.
You can join all the tables together, and then use GROUP_CONCAT like this:
select a.ID_REQUEST, a.CATATAN ,group_concat(t.nama_tipe separator ',') as tipe_request
from tb_requestfix a
INNER JOIN tb_link_tipe_request at
ON(a.id_request = at.id_request)
INNER JOIN tb_tipe_request t
ON(t.id_tipe = at.id_tipe)
GROUP BY a.id_request

is it possible to update the autoincrement primary key values to the vacant values for mysql table

This is my table with id field as unsigned tinyint PRIMARY KEY with NOT NULL and AUTO_INCREMENT.
+----+
| id |
+----+
| 1 |
| 4 |
|254 |
|255 |
+----+
My application is an embedded application so I am using the small datatypes like tinyint. My total count of id values wont go upto 255. But in case if the in between values are deleted for number of times then inserting the new id value will definitely reach 255 sooner or later.
I have some questions,
Is it possible to set the auto increment feature such that it will be insert the new id to the not existing greater value (here 2)?
If not please suggest some way to handle this issue other than using higher data type for id and updating the higher id values after deleting an id (like if I delete id = 2 update all the id values greater than 2 to id-1 so that all the values remain in sequence while inserting new value).
Append your fields for insert. this will use the lowest free id
INSERT INTO ai (id) (
SELECT a.id+1 FROM ai a
LEFT JOIN ai b ON a.id+1 = b.id
WHERE b.id IS NULL LIMIT 1
)
OR to get also 1
SELECT a.id+1 FROM (
SELECT 0 AS id UNION SELECT id FROM ai
) AS a
LEFT JOIN ai b ON a.id+1 = b.id
WHERE b.id IS NULL
ORDER by a.id ASC
LIMIT 1;
I can't think why you choose to be bound by this arbitrary limit. That said, if were to do this then I would construct a table with all possible integers (1-255) and a flag indicating whether the value was currently in use. So a DELETE becomes UPDATE x SET flag = 0 WHERE id = n. Then the query to find the lowest 0 flag becomes trivial.
#
Edge Goldberg - if you want to reorder the entrys and use auto_increment use this. Then also lst_insertid will work -- : -- After DELETE a ROW
UPDATE abc , (SELECT #nr:=0) AS INIT SET a := #nr := (#nr+1);
ALTER TABLE abc AUTO_INCREMENT=1;
-- INSERT a new one
INSERT INTO abc (a) VALUES(1234);
SELECT LAST_INSERT_ID();
Here is the Sample for set auto_increment
MariaDB []> select * from abc;
+-------+------+
| a | b |
+-------+------+
| 00001 | 2 |
| 00002 | 3 |
| 00004 | 5 |
| 00005 | 6 |
| 00007 | 8 |
| 00008 | 9 |
| 00009 | 10 |
| 00010 | 11 |
| 00012 | 13 |
| 00013 | 14 |
| 00014 | 15 |
| 00015 | 16 |
| 00016 | 17 |
| 00017 | 18 |
| 00018 | 19 |
| 00033 | 34 |
| 00077 | 78 |
| 00555 | 556 |
+-------+------+
18 rows in set (0.00 sec)
MariaDB []> -- After DELETE a ROW
MariaDB []> UPDATE abc , (SELECT #nr:=0) AS INIT SET a := #nr := (#nr+1);
Query OK, 16 rows affected (0.03 sec)
Rows matched: 18 Changed: 16 Warnings: 0
MariaDB []> ALTER TABLE abc AUTO_INCREMENT=1;
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
MariaDB []> select * from abc;
+-------+------+
| a | b |
+-------+------+
| 00001 | 2 |
| 00002 | 3 |
| 00003 | 4 |
| 00004 | 5 |
| 00005 | 6 |
| 00006 | 7 |
| 00007 | 8 |
| 00008 | 9 |
| 00009 | 10 |
| 00010 | 11 |
| 00011 | 12 |
| 00012 | 13 |
| 00013 | 14 |
| 00014 | 15 |
| 00015 | 16 |
| 00016 | 17 |
| 00017 | 18 |
| 00018 | 19 |
+-------+------+
18 rows in set (0.00 sec)
MariaDB []> INSERT INTO abc (a) VALUES(NULL);
Query OK, 1 row affected (0.01 sec)
MariaDB []> SELECT LAST_INSERT_ID();
+------------------+
| LAST_INSERT_ID() |
+------------------+
| 19 |
+------------------+
1 row in set (0.00 sec)
MariaDB []> select * from abc;
+-------+------+
| a | b |
+-------+------+
| 00001 | 2 |
| 00002 | 3 |
| 00003 | 4 |
| 00004 | 5 |
| 00005 | 6 |
| 00006 | 7 |
| 00007 | 8 |
| 00008 | 9 |
| 00009 | 10 |
| 00010 | 11 |
| 00011 | 12 |
| 00012 | 13 |
| 00013 | 14 |
| 00014 | 15 |
| 00015 | 16 |
| 00016 | 17 |
| 00017 | 18 |
| 00018 | 19 |
| 00019 | 20 |
+-------+------+
19 rows in set (0.01 sec)
MariaDB []>

MySQL TRIM SELECT result output

I have following MySQL query result, I want only UserName first part before # it need 10000013 part only, I want to remove example.com part, it is possible by TRIM?
mysql> SELECT UserName,DAY(AcctStartTime), COUNT(ResponseCode='200') FROM table201412 WHERE UserName='10000013#example.com' GROUP BY DATE(AcctStartTime);
+---------------------------+--------------------+------------------------------+
| UserName | DAY(AcctStartTime) | COUNT(ResponseCode='200') |
+---------------------------+--------------------+------------------------------+
| 10000013#example.com | 1 | 3 |
| 10000013#example.com | 2 | 5 |
| 10000013#example.com | 3 | 3 |
+----------------------+--------------------+------------------------------+
10 rows in set (0.00 sec)
I need following result:
+---------------------------+--------------------+------------------------------+
| UserName | DAY(AcctStartTime) | COUNT(ResponseCode='200') |
+---------------------------+--------------------+------------------------------+
| 10000013 | 1 | 3 |
| 10000013 | 2 | 5 |
| 10000013 | 3 | 3 |
+---------------------------+--------------------+------------------------------+
10 rows in set (0.00 sec)
The easiest way is to use substring_index():
select substring_index(UserName, '#', 1) as EmailName
In your query, that would be:
SELECT substring_index(UserName, '#', 1) as EmailName, DAY(AcctStartTime), COUNT(ResponseCode='200')
FROM table201412
WHERE UserName='10000013#example.com'
GROUP BY DATE(AcctStartTime);

How do I select rows from one table as CSV and insert into another table based on a key?

I have two tables testa and testb.
mysql> select * from testa;
+------+-------+
| id | dcac |
+------+-------+
| 1 | hello |
| 2 | world |
+------+-------+
2 rows in set (0.00 sec)
mysql> select * from testb;
+------+------+
| a_id | x |
+------+------+
| 1 | a |
| 1 | b |
| 1 | b |
| 1 | c |
| 2 | x |
+------+------+
5 rows in set (0.00 sec)
How do I add a column (x_list) to testa such that it's the comma-seperated list of xs from testb wherever testa.id is testb.a_id
So the output I'm expecting is somewhat like this -
+------+-------+--------+
| id | dcac | x-list |
+------+-------+--------+
| 1 | hello | a,b,b,c|
| 2 | world | x |
+------+-------+--------+
I tried using some complex join statements and I looked at this http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat (did not really understand much)
But I'm not able to proceed. What do I do?
Thanks.
Try:
SELECT testa.id, testa.dcac, GROUP_CONCAT(testb.x)
FROM testb
INNER JOIN testa ON testb.a_id = testa.id
GROUP BY testb.a_id
You can see result here: http://sqlfiddle.com/#!2/28887/2/0