i have 2 tables for example
user_table level_table
================== ===================
| name | levelid | | id | levelname |
================== ===================
| tom | 1 | | 1 | beginner |
------------------ -------------------
| jon | 2 | | 2 | intermed |
------------------ -------------------
| tom | null | | 3 | expert |
------------------ -------------------
| jon | 1 |
------------------
i need to select user table with levelname only where if null, it will show my defined text such 'no level'. and there's no identical column header.
so it would appear like the left one instead of this right one.
Right result Wrong result
================== ==================
| name | level | | name | level |
================== ==================
| tom | beginner | | tom | beginner |
------------------ ------------------
| jon | intermed | | jon | beginner |
------------------ ------------------
| tom | no level | | tom | beginner |
------------------ ------------------
| jon | beginner | | jon | beginner |
------------------ ------------------
i've tried coalesce but seems there's a mistake where all levelname rows shows the same result.
SELECT name,
COALESCE(
(SELECT levelname FROM user_table,level_table WHERE levelid=id),
'no level') AS level
FROM user_table
It should be like this, you need to join both tables using LEFT JOIN
SELECT a.name, COALESCE(b.levelname, 'no level') levelname
FROM user_table a
LEFT JOIN level_table b
ON a.levelid = b.id
The difference between LEFT JOIN and INNER JOIN is that LEFT JOIN return all rows on the left table whether it has a match on the right table or not while INNER JOIN only return rows that are present on both tables.
Visual Representation of JOINS
Related
I have 3 tables
QUESTION table with below 2 properties
1. ID (serial)
2. Question (varchar)
ANSWER table with below 4 properties
1. ID (serial)
2. QuestionID (foreign key to table QUESTION)
3. StudentID (foreign key to table STUDENT)
4. ANSWER (varchar)
5. SubmitDateTime (datetime)
STUDENT table with below properties
1. ID (serial)
2. Name (varchar)
I just want to show records with each student (one record for each student) with every answer. If any question's answer is not given by the student it will show blank.
For example:
QUESTION TABLE
| ID | QUESTION |
|----- | --------- |
| 1 | A FOR? |
| 2 | B FOR? |
| 3 | C FOR? |
ANSWER TABLE
| ID | QuestionID | StudentID | ANSWER | SubmitDateTime |
|----- | ----------- |------------|--------|----------------|
| 1 | 1 | 1 |Apple | something date |
| 2 | 1 | 2 |Ant | something date |
| 3 | 2 | 1 |Book | something date |
| 4 | 3 | 2 |Cat | something date |
STUDENT TABLE
| ID | NAME |
|----- | --------- |
| 1 | Jhon |
| 2 | Lily |
Expected Records
Result table
| ID | NAME | Answers |
|----- | --------- | ---------------------|
| 1 | Jhon | Apple,Book,<blank> |
| 2 | Lily | Ant,<blank>,Cat |
"blank" means no record will be shown instead of a blank space or a hyphane.
My implementation:
SELECT s.ID,s.Name,
GROUP_CONCAT(a.answer SEPARATOR ',') AS answers
FROM student AS s
LEFT JOIN answer AS a ON a.studentID=s.ID
WHERE a.submitdate BETWEEN '<somedate>' AND '<somedate>'
GROUP BY s.ID ORDER BY a.ID ASC
It does not give me a blank answer. How to get these?
Try this:
SELECT sid, sname, GROUP_CONCAT(IFNULL(a.answer,'-') ORDER BY qid)
FROM
(SELECT q.id AS qid, s.id AS sid, s.Name AS sname
FROM question q CROSS JOIN student s) qs
LEFT JOIN answer a ON qs.qid=a.QuestionID AND qs.sid=a.StudentID
GROUP BY sid, sname;
The base query is a CROSS JOIN between question and student tables that will be a subquery and give a result like this:
+-----+-----+-------+
| qid | sid | sname |
+-----+-----+-------+
| 1 | 2 | Lily |
| 1 | 1 | Jhon |
| 2 | 2 | Lily |
| 2 | 1 | Jhon |
| 3 | 2 | Lily |
| 3 | 1 | Jhon |
+-----+-----+-------+
As you can see, each of the student will be paired with all of the existing question regardless of their answer records in answer table. This will be the reference for the LEFT JOIN with answer table.
Demo fiddle
Let's say I have two tables, one with firstnames, and another with lastnames:
firstnametable
---------------------------------------------
| id | firstname | |
---------------------------------------------
| 1 | John | |
| 2 | Pete | |
---------------------------------------------
lastnametable
---------------------------------------------
| id | lastname | firstname_id | active |
---------------------------------------------
| 1 | Dough | 1 | 0 |
| 2 | Do | 1 | 1 |
| 2 | Sampres | 2 | 1 |
---------------------------------------------
I am looking for Query such that it would appear as if it came from a single table:
firstnametable
---------------------------------------------
| id | firstname | lastname | |
---------------------------------------------
| 1 | John | Do | |
| 2 | Pete | Sampres | |
---------------------------------------------
But it is important for me that the results are delivered in such a fashion that the prefix is also as if the results are all from the original table, ie:firstnametable.firstname and firstnametable.lastname
Is this at all possible?
My current solution is:
SELECT firstnametable.id,
firstnametable.firstname,
CONCAT(jointable.name) as lastname
FROM firstnametable
LEFT JOIN (
SELECT lastname
FROM lastnametable
WHERE active = 1
) as jointable ON (firstnametable.id = jointable.firstname_id)
But I am still missing my desired firstnametable prefix for the lastname column.
You need to include the firstname id in the jointtable select and I don't know what the purpose of the concat is since you aren't concating anything but you haven't selected name anywhere perhaps you meant lastname. If you want to include the table name in the headers use an alias.
SELECT firstnametable.id as 'firstnametable.id',
firstnametable.firstname as 'firstnametable.firstname',
jointable.lastname as 'firstnametable.lastname'
FROM firstnametable
LEFT JOIN (
SELECT firstname_id,
lastname
FROM lastnametable
WHERE active = 1
) as jointable ON firstnametable.id = jointable.firstname_id;
+-------------------+--------------------------+-------------------------+
| firstnametable.id | firstnametable.firstname | firstnametable.lastname |
+-------------------+--------------------------+-------------------------+
| 1 | John | Do |
| 2 | Pete | Sampres |
+-------------------+--------------------------+-------------------------+
2 rows in set (0.001 sec)
I have two MySQL tables (table_a and table_b) and a join table (table_c).
Table Structures:
table_a:
__________________
| table_a: |
|----------------|
| id |
| result_column |
------------------
table_b:
__________________
| table_b: |
|----------------|
| id |
| name |
------------------
table_c:
__________________
| table_c: |
|----------------|
| id |
| table_a_id |
| table_b_id |
------------------
My Goal:
I want to find a query that will:
Iterate over every table_a record and get the table_a.id value
Find any records in table_c which have a matching table_c.table_a_id value
For each matching record in table_c get the table_c.table_b_id value
Find the record in table_b which has a matching table_b.id value
For that matching record in table_b get the table_b.name value
In table_a, concatenate each matched name value into the corresponding table_a.result_column
Example:
Before the Query:
_______________________ _________________________________ ________________
| table_a: | | table_c: | | table_b: |
|---------------------| |-------------------------------| |--------------|
| id | result_column | | id | table_a_id | table_b_id | | id | name |
|-----|---------------| |-----|------------|------------| |-----|--------|
| 1 | | | 1 | 1 | 3 | | 1 | Kevin |
| 2 | | | 2 | 1 | 4 | | 2 | Jesse |
| 3 | | | 3 | 2 | 2 | | 3 | Karen |
----------------------- | 4 | 3 | 1 | | 4 | Tim |
| 5 | 3 | 5 | | 5 | Lauren |
--------------------------------- ----------------
After the Query:
_______________________ _________________________________ ________________
| table_a: | | table_c: | | table_b: |
|---------------------| |-------------------------------| |--------------|
| id | result_column | | id | table_a_id | table_b_id | | id | name |
|-----|---------------| |-----|------------|------------| |-----|--------|
| 1 | Karen, Tim | | 1 | 1 | 3 | | 1 | Kevin |
| 2 | Jesse | | 2 | 1 | 4 | | 2 | Jesse |
| 3 | Kevin, Lauren | | 3 | 2 | 2 | | 3 | Karen |
----------------------- | 4 | 3 | 1 | | 4 | Tim |
| 5 | 3 | 5 | | 5 | Lauren |
--------------------------------- ----------------
For absolute clarity, I understand that this is incredibly bad practice within a relational data-table. This is as far from normalization as one can get. I would never design a database like this. I was tasked with creating a custom column with a list of values purely for a business case.
The query you seem to want is:
select c.table_a_id, group_concat(b.name separator ', ')
from c join
b
on c.table_b_id = b.id
group by c.table_a_id;
If you actually want to update a, you can put this into an update statement:
update a join
(select c.table_a_id, group_concat(b.name separator ', ') as names
from c join
b
on c.table_b_id = b.id
group by c.table_a_id
) cb
on cb.table_a_id = a.id
set result_column = cb.names
Previous answer is close; but you also required that you only want the records matched in table C that are in A.
The first query does not meet this requirement; but the update statement does, as it will only update records in table A, if the id matches the table_a_id value pulled from table C.
Given what you said you wished for the end result, the update statement above would work.
If you wish to be explicit in your logic, just add a join from table A to table C.
select a.id, group_concat(b.name separator ', ')
from a
join c ON (a.id = c.table_a_id)
join b ON (c.table_b_id = b.id)
group by a.id;
I have a table name= wspollokator
-----------------
| user1 | user2 |
-----------------
| 1 | 3 |
-----------------
| 3 | 1 |
-----------------
| 7 | 0 |
-----------------
| 8 | 10 |
-----------------
| 9 | 0 |
-----------------
| 10 | 8 |
-----------------
I know how to display it like above:
SELECT p1.user1, p1.user2
FROM wspollokator p1
LEFT JOIN wspollokator p2 ON p1.user1 = p2.user2
WHERE p1.user1 <> p1.user2
but this is a relational table only with user ids
in another table name: zakwalifikowani
I have firstnames and lastnames of user1 and user2. The key is user1 user2
---------------------------------------------------
|firstname1 | lastname1 | firstname2 | lastname2 |
---------------------------------------------------
| Tom | Hopkins | Mike | Ariston |
---------------------------------------------------
| Mike | Ariston | Tom | Hopkins |
---------------------------------------------------
| Marlon | Nickolson | | |
---------------------------------------------------
| John | Nash | Jason | Lin |
---------------------------------------------------
| Johny | Bride | | |
---------------------------------------------------
| Jason | Lin | John | Nash |
---------------------------------------------------
How can I use columns user1 and user2 to display it like above? I think that I need use query above because this query allow me to connect people into pairs
You need a "foreign key" in table zakwalifikowani before you can join "user1=1" on "firstname1=Tom" (for example).
I am going to assume that your first query is really:
SELECT p1.user1, p1.user
FROM wspollokator p1
WHERE p1.user1 <> p1.user2;
The left join does nothing for the query.
To get names, you want two joins. Here is an example:
SELECT w1.FirstName as FirstName1, w1.LastName as LastName1,
w2.FirstName as FirstName2, w2.LastName as LastName2
FROM wspollokator p1 LEFT JOIN
zakwalifikowani w1
ON p1.user1 = w1.user LEFT JOIN
zakwalifikowani w2
ON p1.user2 = w2.user
WHERE p1.user1 <> p1.user2;
I have a db in mysql with multiple tables and would like to join multiple tables into one view to save me from having to build 3 or 4 sql statements or even one large joining statement in php to get the same info.
Here are all my tables that I want to join
track_title
+----+------------------+
| ID | TITLE |
+----+------------------+
| 1 | Title Here |
| 2 | Another Title |
| 3 | Some Other Title |
+----+------------------+
track_artist
+----+----------------+-----------+-----------+
| ID | TRACK_TITLE_ID | ARTIST_ID | SYMBOL_ID |
+----+----------------+-----------+-----------+
| 1 | 1 | 1 | 2 |
| 2 | 1 | 2 | 1 |
| 3 | 3 | 1 | 1 |
+----+----------------+-----------+-----------+
artist
+----+-------------+
| ID | ARTIST |
+----+-------------+
| 1 | Linkin Park |
| 2 | Metallica |
+----+-------------+
symbol
+----+--------+
| ID | SYMBOL |
+----+--------+
| 1 | |
| 2 | Feat. |
+----+--------+
tracklisting
+----+----------+----------+---------------+---------+
| ID | TRACK NO | TITLE_ID | VERSION | DISC NO |
+----+----------+----------+---------------+---------+
| 1 | 1 | 1 | | 1 |
| 2 | 1 | 2 | Album Version | 1 |
| 3 | 1 | 3 | Live Version | 1 |
+----+----------+----------+---------------+---------+
This is the final view I'm looking for
+----+----------+------------------+---------------+-----------------------------+---------+
| ID | TRACK NO | TITLE | VERSION | ARTIST | DISC NO |
+----+----------+------------------+---------------+-----------------------------+---------+
| 1 | 1 | Title Here | | Linkin Park Feat. Metallica | 1 |
| 2 | 1 | Another Title | Album Version | | 1 |
| 3 | 1 | Some Other Title | Live Version | Linkin Park | 1 |
+----+----------+------------------+---------------+-----------------------------+---------+
I have been bashing my head for the past 3 days with left, right, join and full join and just can't seem to get this to work.
Basically what I want to happen is the track_artist table will get the artist and symbol form the respective tables and concat them together into one column. Then join title and the concat column to have this view.
full_artist_view
+----------+------------------+-----------------------------+
| TITLE_ID | TITLE | FULL_ARTIST |
+----------+------------------+-----------------------------+
| 1 | Title Here | Linkin Park Feat. Metallica |
| 2 | Another Title | |
| 3 | Some Other Title | Linkin Park |
+----------+------------------+-----------------------------+
I have gotten this far but when I try join this to the tracklisting table I seem to crash my server which is getting very painful. No mysql error so I'm guessing I'm using the wrong join or this is just not possible.(though I can't see how this is not possible)
The tracklisting table is continuesly growing every week by 1000 records comfortable and is sitting at +- 75000 records.
To me this is the sql that should work, but doesn't
FROM full_artist_view LEFT JOIN tracklisting ON
full_artist_view.TITLE_ID = tracklisting.TITLE_ID
While I have only your small data sample and I can't see what your full_artist_view code looks like. You should be able to get the result using the following:
select tt.id,
tl.`track no`,
tt.title,
coalesce(tl.version, '') version,
group_concat(concat(coalesce(a.artist, ''), ' ', coalesce(s.symbol, '')) order by a.artist SEPARATOR ' ') artist,
tl.`disc no`
from track_title tt
inner join tracklisting tl
on tt.id = tl.TITLE_ID
left join track_artist ta
on tt.id = ta.TRACK_TITLE_ID
left join artist a
on ta.artist_id = a.id
left join symbol s
on ta.symbol_id = s.id
group by tt.id, tl.`track no`, tt.title, tl.version, tl.`disc no`
See SQL Fiddle with Demo. This returns:
| ID | TRACK NO | TITLE | VERSION | ARTIST | DISC NO |
---------------------------------------------------------------------------------------------
| 1 | 1 | Title Here | | Linkin Park Feat. Metallica | 1 |
| 2 | 1 | Another Title | Album Version | | 1 |
| 3 | 1 | Some Other Title | Live Version | Linkin Park | 1 |
Quick play, and I think (but not certain) it is something like this that you need:-
SELECT a.Id, a.Track_No, b.Title, a.Version, GROUP_CONCAT(CONCAT(d.Artists, e.Symbol)), a.Disc_No
FROM tracklisting a
INNER JOIN track_title b ON a.Title_id = b.Id
LEFT OUTER JOIN track_artist c ON b.Id = c.Track_Title_Id
LEFT OUTER JOIN artist d ON c.Artist_Id = d.Id
LEFT OUTER JOIN symbol e ON d.SymbolId = e.Id
GROUP BY a.Id, a.Track_No, b.Title, a.Version, a.Disc_No
But I might have missed something so let me know!