MySql query for displaying rows as column dyanmically - mysql

I've to join three tables the resultant output will be like this
+---------------+--------------+-------------+-------------+
| Category_Name | English | French | German |
+---------------+--------------+-------------+-------------+
| Clothing | english_name | french_name | german_name |
| Electronics | NULL | NULL | NULL |
| Ornaments | NULL | NULL | NULL |
+---------------+--------------+-------------+-------------+
Following is my table_structure
tbl_category
+----+---------------+
| id | category_name |
+----+---------------+
| 1 | Clothing |
| 2 | Electronics |
| 3 | Ornaments |
+----+---------------+
tbl_languages
+----+----------+
| id | language |
+----+----------+
| 1 | English |
| 2 | French |
| 3 | German |
+----+----------+
tbl_languages_data
+----+-------------+-------------+---------------+
| id | language_id | category_id | category_name |
+----+-------------+-------------+---------------+
| 1 | 1 | 1 | english_name |
| 2 | 2 | 1 | french_name |
| 3 | 3 | 1 | german_name |
+----+-------------+-------------+---------------+
I've two questions.
1. Are these relations are valid or there can be some other way to avoid deadlocks
2. What will be the query for getting this result.
Note: The output should be dynamic as I've to add more data to tbl_language.

Should be something along the lines of:
SELECT Category_Name
MAX(CASE when lan.language_id = 1 THEN lan.category_name END) as 'English',
MAX(CASE when lan.language_id = 2 THEN lan.category_name END) as 'French',
MAX(CASE when lan.language_id = 3 THEN lan.category_name END) as 'German'
FROM tbl_category cat
RIGHT JOIN tbl_languages_data lan ON cat.id = lan.category_id
GROUP BY Category_Name
NOTE: Did not notice your edit, I don't think you will be able to dynamically add columns to the expected result. Please somebody correct me if I am wrong.

I would omit the last column Category Name from tbl_languages_data. And refer the Language_id as an number, this way you will compare the two indexes with the same datatype (int to int). This will be faster than a string with an int. This will result in the following query:
SELECT cat.category_name
, lang.language
FROM tbl_category AS cat
LEFT JOIN tbl_languages_data AS lang_data
ON lang_data.category_id = cat.id
LEFT JOIN tbl_languages AS lang
ON lang_data.language_id = lang.id
Note that this is different than your expected result set. The three languages are now translated into one column. And here is your table design:
tbl_category
+----+---------------+
| id | category_name |
+----+---------------+
| 1 | Clothing |
+----+---------------+
| 2 | Electronics |
+----+---------------+
| 3 | Ornaments |
+----+---------------+
tbl_languages
+----+----------+
| id | language |
+----+----------+
| 1 | English |
+----+----------+
| 2 | French |
+----+----------+
| 3 | German |
+----+----------+
tbl_languages_data
+----+-------------+-------------+
| id | language_id | category_id |
+----+-------------+-------------+
| 1 | 1 | 1 |
+----+-------------+-------------+
| 2 | 2 | 1 |
+----+-------------+-------------+
| 3 | 3 | 1 |
+----+-------------+-------------+

Related

How to combine multiple rows into a column based on a condition in Mysql?

I have two tables as follows.
Category table
+------------+------------+--------------+
| CategoryID | Name | CategoryCode |
+------------+------------+--------------+
| 1 | Fixed | |
| 2 | Consumable | |
| 3 | Intangible | |
+------------+------------+--------------+
Type table
+--------+------------+-------------------------+----------+
| TypeID | CategoryID | Name | TypeCode |
+--------+------------+-------------------------+----------+
| 1 | 1 | Furniture | |
| 2 | 1 | Computers & Peripherals | |
| 3 | 2 | Keyboards | |
| 4 | 2 | Other | |
| 5 | 3 | Software | |
+--------+------------+-------------------------+----------+
The result I want is like this
+------------+------------+------------------------------------+
| CategoryID | Category | Types |
+------------+------------+------------------------------------+
| 1 | Fixed | Furniture, Computers & Peripherals |
| 2 | Consumable | Keyboards, other |
| 3 | Intangible | Software |
+------------+------------+------------------------------------+
Appriciate if you could help me with wirting the query in MySQL
You can try this solution
SELECT
a.CategoryId,
a.`Name` Category,
GROUP_CONCAT(b.`Name`) Types
FROM
Category a
INNER JOIN Type b ON b.CategoryID = a.CategoryId
GROUP BY a.CategoryId

I need help for many to many relation query

I have working on database for dictionary project. I have to store a word and meaning with many to many relationship.
Below I have mentioned the sample with my table structure. I hope the table structure is right, but I don't know how to select all meanings for single word while user searching.
And also I have to write a query to select all word and synonyms linked to a single meaning. And also I have to write a query to select all meaning and synonyms linked to a single word.
word_table
+----+------+
| id | word |
+----+------+
| 1 | A |
| 2 | B |
| 3 | C |
+----+------+
meaning_table
+----+--------+
| id | meaning|
+----+--------+
| 1 | X |
| 2 | Y |
| 3 | Z |
+----+--------+
word_meaning_table
+---------+-----------+
| word_id | meaning_id|
+---------+-----------+
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 1 |
| 2 | 3 |
| 3 | 2 |
| 3 | 3 |
+---------+-----------+
synonyms_table
+----+--------+
| id | synonys|
+----+--------+
| 1 | aa |
| 2 | bb |
| 3 | cc |
+----+--------+
word_synonyms_table
+---------+-----------+
| word_id | synonym_id|
+---------+-----------+
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
+---------+-----------+
Expected output should be like this.
If user searching for a word "A" in word table the result should be
Result for word "A"
+----+----------+---------+
| word| meaning | synonys |
+----+----------+---------+
| A | X | aa |
| A | Y | bb |
| A | Z | cc |
+----+----------+---------+
You just need many joins:
SELECT w.word,m.meaning,s.synonys
FROM word_table w
INNER JOIN word_meaning_table wm
ON(w.id = wm.word_id)
INNER JOIN meaning_table m
ON(wm.meaning_id = m.id)
INNER JOIN word_synonyms_table ws
ON(w.id = ws.word_id)
INNER JOIN synonyms_table s
ON(ws.synonym_id = s.id)
Let me reffer you to this document that explain all about join syntax's.

Complex MySQL Query for Many-to-Many

I have searched and gone through the available topics similar to mine. But, failed to find that satisfies my requirements. Hence, posting it here.
I have four tables as follows:
"Organization" table:
--------------------------------
| org_id | org_name |
| 1 | A |
| 2 | B |
| 3 | C |
"Members" table:
----------------------------------------------
| mem_id | mem_name | org_id |
| 1 | mem1 | 1 |
| 2 | mem2 | 1 |
| 3 | mem3 | 2 |
| 4 | mem4 | 3 |
"Resource" table:
--------------------------------
| res_id | res_name |
| 1 | resource1 |
| 2 | resource2 |
| 3 | resource3 |
| 4 | resource4 |
"member-resource" table:
--------------------------------------------
| sl_no | mem_id | res_id |
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 2 | 1 |
| 4 | 4 | 3 |
| 5 | 3 | 4 |
| 6 | 2 | 3 |
| 7 | 4 | 3 |
I want to find out the total number of distinct resources according to organizations. Expected output is as follows:
| org_name | Total Resources |
| A | 3 |
| B | 1 |
| C | 1 |
I also want to find out the total number of shared resources according to organizations. Expected output is as follows:
| org_name | Shared Resources |
| A | 1 |
| B | 0 |
| C | 1 |
Any help in this regard will highly be appreciated.
Regards.
It is much simpler than you think, particularly because you don't even need the resource table:
SELECT o.org_name, COUNT(DISTINCT mr.res_id) TotalResources
FROM member_resource mr
JOIN members m ON mr.mem_id = m.mem_id
JOIN organization o ON m.org_id = o.org_id
GROUP BY o.org_id
Output:
| ORG_NAME | TOTALRESOURCES |
|----------|----------------|
| A | 3 |
| B | 1 |
| C | 1 |
Fiddle here.
Try this query below.
SELECT org_name, COUNT(DISTINCT res_id)
FROM organization, members, member-resource
WHERE members.mem_id = member-resource.mem_id
AND organization.org_id = members.org_id
GROUP BY org_id, org_name

MYSQL - Join 2 tables with full rows on left table

Could you please help me to resolve this issue?
I have 2 tables as below:
attributes
| id | name |
|----+--------------|
| 1 | first_name |
| 2 | last_name |
| 3 | email |
attribute_values
| uid | attr_id | value |
|-------+-----------|-----------|
| 1 | 1 | Hello |
| 1 | 2 | world |
|-------+-----------|-----------|
| 2 | 1 | A |
| 2 | 2 | B |
| 2 | 3 | a#xzy.com |
I want to write a query to select attributes of a user even if attribute is not exist in table attribute_values. Then, I would like to get result with null value.
For example for selecting user id 1
| name | value |
|---------------|-----------|
| first_name | Hello |
| last_name | world |
| email | NULL |
user id 2
| name | value |
|---------------|-----------|
| first_name | A |
| last_name | B |
| email | a#xzy.com |
user id 3 (not exist in attribute_values)
| name | value |
|---------------|-----------|
| first_name | NULL |
| last_name | NULL |
| email | NULL |
Is there best way with one query to get result as 3 above examples?
Thanks.
SELECT a.*, b.value
FROM attributes a
LEFT JOIN attribute_values b
ON a.ID = b.attr_id AND b.uid = 1
SQLFiddle Demo

MYSQL results need to combine tables

I'm scripting a tool with PHP and I've illustrated a situation with MYSQL. I have two tables which I need to combine to get the results I want.
I came up with this:
SELECT * FROM names, dogs WHERE dog_id = dogs.id;
but when I do this, the results do NOT include the rows where dog_id = NULL. And I need those results too.
TABLE NAMES
| *id* | *name* | *dog_id* |
| 1 | name1 | NULL |
| 2 | name2 | 1 |
| 3 | name3 | NULL |
| 4 | name4 | 2 |
TABLE DOGS
| *id* | *dog* |
| 1 | dog1 |
| 2 | dog2 |
How to get these results:
RESULTS
| *id* | *name* | *dog_id* | *dog* |
| 1 | name1 | NULL | NULL |
| 2 | name2 | 1 | dog1 |
| 3 | name3 | NULL | NULL |
| 4 | name4 | 2 | dog2 |
Use an outer join:
SELECT names.id, names.name, names.dog_id, dogs.dog
FROM names
LEFT JOIN dogs
ON dog_id = dogs.id;