I have three tables like this:
Animal
| id | cat_id | horse_id | dog_id |
|:--:|:------:|:--------:|--------|
| 1 | 15 | 16 | 17 |
Cat
| id | lang_id |
|:--:|:-------:|
| 15 | 3716 |
Horse
| id | lang_id |
|:--:|:-------:|
| 16 | 3717 |
Dog
| id | lang_id |
|:--:|:-------:|
| 17 | 3718 |
Language
| id | en |
|:----:|:--------------:|
| 3716 | BRAVE LEGEND |
| 3717 | N Rawiller |
| 3718 | DRAGON GENERAL |
I want to get all the animals en name from Language table through each animal's table lang_id. It would be like by using Animal: cat_id -> Cat: lang_id -> Language: en. The final results would be like:
| animal_id | cat_name | horse_name | dog_name |
|:---------:|:------------:|:----------:|:--------------:|
| 1 | BRAVE LEGEND | N Rawiller | DRAGON GENERAL |
I am trying to use this:
select animal.id, lang.* from animal
left join cat on animal.cat_id = cat.id
left join horse on animal.horse_id = horse.id
left join dog on animal.dog_id = dog.id
left join lang on cat.lang_id = lang.id or (horse.lang_id = lang.id) or (dog.lang_id = lang.id)
where animal.id = 1
But I can't get cat_name, dog_name, horse_name because it's all coming from the same Language table.
Try below query:
You need to JOIN lang table multiple times, using one JOIN with multiple OR will not give you desired result,
SELECT animal.id, lang.en as cat_name,l1.en as horse_name,l2.en as dog_name
FROM animal
LEFT JOIN cat ON animal.cat_id = cat.id
LEFT JOIN horse ON animal.horse_id = horse.id
LEFT JOIN dog ON animal.dog_id = dog.id
LEFT JOIN lang ON cat.lang_id = lang.id
LEFT JOIN lang l1 ON horse.lang_id = l1.id
LEFT JOIN lang l2 ON dog.lang_id = l2.id
WHERE animal.id = 1
Try this:
select animal.id, lang1.cat_name, lang2.horse_name, lang3.dog_name
from animal
left join cat on animal.cat_id = cat.id
left join horse on animal.horse_id = horse.id
left join dog on animal.dog_id = dog.id
left join lang AS lang1 on cat.lang_id = lang1.id
left join lang AS lang2 ON horse.lang_id = lang2.id
left join lang AS lang3 ON (dog.lang_id = lang3.id)
where animal.id = 1
Try this:
SELECT a.id, lang1.en as cat_name,lang2.en as horse_name,lang3.en as dog_name
FROM `animal` a
LEFT JOIN cat c ON c.id = a.cat_id
LEFT JOIN LANGUAGE l on l.id=c.lang_id
LEFT JOIN dog d ON d.id = a.dog_id
LEFT JOIN horse h ON h.id = a.horse_id
LEFT JOIN language lang1 ON c.lang_id=lang1.id
LEFT JOIN language lang2 ON h.lang_id=lang2.id
LEFT JOIN language lang3 ON d.lang_id=lang3.id
Related
How do I build a joint to select either table
Table jobs
Id | name | salary | company | type
1 | php | 17.850 | 5 | 1
2 | mysql | 4.500 | 89 | 2
2 | nodejs | 7.500 | 89 | 1
Table Company
Id | name | Area | status
1 | Facebook| Developer| 1
2 | Google | Manager | 1
Table Candidate
Id | name | City | phone
1 | Alan Kout | Nevada | 1 555 6666
2 | Wagner Mom | L.A. | 1 444 8965
My query mysql, inner join candidate or company
If type == 1 in table jobs INNER JOIN ON table company
If type == 2 in table jobs INNER JOIN ON table candidate
Example
SELECT * FROM table_jobs
IF(table_jobs.type == 1, INNER JOIN table_company, INNER JOIN table_candidate)
This is possible?
You can achieve this using a LEFT JOIN instead of an INNER JOIN:
SELECT *
FROM table_jobs tj
LEFT JOIN table_company tco ON tj.type = 1 AND tco.id = tj.id
LEFT JOIN table_candidate tca ON tj.type = 2 AND tca.id = tj.id
This will join to table_company where the type is 1, and table_candidate where the type is 2.
You can then SELECT whichever columns are needed from each table as appropriate.
Use left join and coalesce():
SELECT tj.*,
coalesce(co.name, ca.name) as name,
. . .
FROM table_jobs tj LEFT JOIN
table_company co
ON co.id = tj.id and tj.type = 1 LEFT JOIN
table_candidate ca
ON ca.id = tj.id and tj.type = 2;
If you want both joins in one result you can use the UNION operator
SELECT *
FROM table_jobs INNER JOIN table_company
WHERE table_jobs.type=1
UNION
SELECT *
FROM table_jobs INNER JOIN table_candidate
WHERE table_jobs.type=2
I have written the following query:
select title, branch_name, no_of_copies
from Book_Copies BC
inner join Book B on BC.book_id = B.book_id
inner join Library_Branch LB on BC.branch_id = LB.branch_id
where title = 'Grapes of Wrath';
But my issue is that this displays only the titles and branch names that have > 0 no_of_copies. How do I display ones that do not have a no_of_copies row? (Where it would be equal to 0).
Here is the table I currently get:
+-----------------+-------------+--------------+
| title | branch_name | no_of_copies |
+-----------------+-------------+--------------+
| Grapes of Wrath | Central | 5 |
| Grapes of Wrath | Allentown | 2 |
+-----------------+-------------+--------------+
This is what I need it to be:
+-----------------+-------------+--------------+
| title | branch_name | no_of_copies |
+-----------------+-------------+--------------+
| Grapes of Wrath | Central | 5 |
| Grapes of Wrath | Allentown | 2 |
| Grapes of Wrath | Sharpstown | 0 |
+-----------------+-------------+--------------+
You need to use an outer join instead starting from the book table. Perhaps something like this:
select title, branch_name, no_of_copies
from Book B
left join Book_Copies BC on BC.book_id = B.book_id
left join Library_Branch LB on BC.branch_id = LB.branch_id
where title = 'Grapes of Wrath';
Reading your comments, it sounds like you want to use a cross join between book and library_branch to get all combinations of books and branches (otherwise known as a cartesian product). Then outer join those results to the lookup table:
select title, branch_name, coalesce(no_of_copies,0) copies
from Book B
cross join Library_Branch LB
left join Book_Copies BC on BC.book_id = B.book_id
and BC.branch_id = LB.branch_id
where title = 'Grapes of Wrath';
I have 3 tables
Table cases: docket is pk
| docket | dt_file |
-----------------------
|AA-0322 | 01-22-2015 |
|AA-0431 | 03-21-2014 |
Table parties:
| id | docket | name |
----------------------------
| 1 | AA-0322 | Bob |
| 2 | AA-0322 | John |
Table motions:
| id | docket | motion |
-----------------------------
| 1 | AA-0322 | Summons|
| 2 | AA-0322 | Guilty |
I want to count the number of fields in parties and motion that have the same docket and then make a table with table.cases with the dt_file
example:
| docket | party_count | motion_count| dt_file |
-----------------------------------------------
AA-0322| 2 | 2 | 02-22-2015|
I also want to filter by dt_file, so adding a WHERE statement ex:
WHERE YEAR(dt_file) = '2015'
So far i've came up with this, but I havn't had success joining table.cases with dt_file correctly.
SELECT p.docket, p.party_count, m.motion_count
FROM
(SELECT docket, COUNT(docket) AS party_count
FROM parties
GROUP BY docket) AS p
INNER JOIN
(SELECT docket, COUNT(docket) AS motion_count
FROM motions
GROUP BY docket) AS m
ON p.docket = m.docket
Your query seems correct. You just need to add cases to the from clause:
SELECT c.docket, p.party_count, m.motion_count, c.dt_file
FROM cases c JOIN
(SELECT docket, COUNT(docket) AS party_count
FROM parties
GROUP BY docket
) p
ON c.docket = p.docket INNER JOIN
(SELECT docket, COUNT(docket) AS motion_count
FROM motions
GROUP BY docket
) m
ON c.docket = m.docket;
If you want all dockets, even those where there are no motions or parties, then use LEFT JOIN.
Let this be another example.
Select
p.docket,
COUNT(p.docket) As party_count,
COUNT(m.docket) As motion_count,
p.dt_file
From
cases As c
Inner Join parties As p
On c.docket = p.docket
Inner Join motions As m
On c.docket = m.docket
Group By
p.docket,
p.dt_file
Try this:
SELECT p.docket, p.party_count, m.motion_count, c.dt_file
FROM
(SELECT docket, COUNT(docket) AS party_count
FROM parties
GROUP BY docket) AS p
INNER JOIN
(SELECT docket, COUNT(docket) AS motion_count
FROM motions
GROUP BY docket) AS m
ON p.docket = m.docket
INNER JOIN cases c
ON p.docket = c.docket
WHERE YEAR(c.dt_file) = '2015'
I'm working on a product database (PDB) to be used both for a webshop and as articles in our ERP-system. Most of the data comes directly from our suppliers as CSV-files, and we've added options to override certain fields, which has resulted in a table structure I can't figure out how to efficiently query.
In essence the table structure consists of two tables, article and extended_article, where the last table contains a field called parent_article_code used to combine women articles into men for display purposes. Not all articles contain extended_articles and not all articles with extended_articles has a value in parent_article_code.
I need to perform a query returning all articles with a match, but only show the parent article where either the parent or child matches the query. This is a really simplefied version of the tables and I'll also add a query to show how the data is actually structured.
article table:
-------------------------------------------------------------------------
| id | code | name | description |
| 1 | 029320 | T-shirt | Nice t-shirt with awsome logo |
| 2 | 029321 | T-shirt Lady | Nice t-shirt with awsome logo |
| 3 | 029322 | Sweatshirt | Nice sweatshirt with awsome logo |
| 4 | 029323 | Pants | Nice pants with awsome logo |
-------------------------------------------------------------------------
extended_article table:
-------------------------------------------------------------------------------------------------
| id | article_code | parent_article_code | name_override | description_override |
| 1 | 029320 | | T-shirt with print | |
| 2 | 029321 | 029320 | | |
| 3 | 029323 | | Awsome pants! | |
-------------------------------------------------------------------------------------------------
Example SQL query (returning all records with match - not only children):
SELECT article.*,
article.id,
extended_article.parent_article_code,
extended_article.impressions,
extended_article.is_base_assortment,
extended_article.is_visible,
extended_article.name_override,
extended_article.description_override,
extended_article.additional_description,
extended_article.preferred_image_file_name,
supplier.name AS supplier_name,
brand.name AS brand_name
FROM article
LEFT OUTER JOIN article_sort_order
ON article_sort_order.article_code = article.code AND category_id IS NULL
LEFT OUTER JOIN extended_article
ON extended_article.article_code = article.code
LEFT JOIN supplier
ON supplier.id = article.supplier_id
LEFT JOIN brand
ON brand.id = article.brand_id
WHERE (extended_article.is_base_assortment = 1)
AND (article.is_expired = 0)
AND (extended_article.is_visible = 1)
AND ((EXISTS
(
SELECT 1
FROM article_color_groups
WHERE article_color_groups.article_code = article.code
AND article_color_groups.color_group_id = 4
)
))
So my question is this:
How can I efficently query this table structure and have a result set that only contains the parent articles?
EDIT:
I had an idea to move the query part into two subqueries selecting only IDs and using UNION to generate a list to select the appropriate fields from. This seems to work, but might not be the most efficient solution?
SELECT article.*, article.id, extended_article.parent_article_code, extended_article.impressions, extended_article.is_base_assortment, extended_article.is_visible, extended_article.name_override, extended_article.description_override, extended_article.additional_description, extended_article.preferred_image_file_name, supplier.name AS supplier_name, brand.name AS brand_name
FROM article
LEFT OUTER JOIN article_sort_order ON article_sort_order.article_code = article.code AND category_id IS NULL
LEFT OUTER JOIN extended_article ON extended_article.article_code = article.code
LEFT JOIN supplier ON supplier.id = article.supplier_id
LEFT JOIN brand ON brand.id = article.brand_id
WHERE article.code IN (
SELECT article.code
FROM article
LEFT OUTER JOIN article_sort_order ON article_sort_order.article_code = article.code AND category_id IS NULL
LEFT OUTER JOIN extended_article ON extended_article.article_code = article.code
LEFT JOIN supplier ON supplier.id = article.supplier_id
LEFT JOIN brand ON brand.id = article.brand_id
WHERE (NULLIF(extended_article.parent_article_code, '') IS NULL)
AND
(extended_article.is_base_assortment = 1)
AND
(article.is_expired = 0)
AND
(extended_article.is_visible = 1)
AND
((EXISTS (SELECT 1 FROM article_color_groups WHERE article_color_groups.article_code = article.code AND article_color_groups.color_group_id = 11)))
UNION
SELECT extended_article.parent_article_code
FROM article
LEFT OUTER JOIN article_sort_order ON article_sort_order.article_code = article.code AND category_id IS NULL
LEFT OUTER JOIN extended_article ON extended_article.article_code = article.code
LEFT JOIN supplier ON supplier.id = article.supplier_id
LEFT JOIN brand ON brand.id = article.brand_id
WHERE (NULLIF(extended_article.parent_article_code, '') IS NOT NULL)
AND
(article.is_expired = 0)
AND
((EXISTS (SELECT 1 FROM article_color_groups WHERE article_color_groups.article_code = article.code AND article_color_groups.color_group_id = 11)))
)
ORDER BY -article_sort_order.sort_order DESC;
I am trying to use my query to find the specific Worker.wname that has none of his relations with the animal.wild is TRUE.
for example from the following table I need to return "Yossi" since he has no row with wild = t
wname | type | wild
-------+-----------+------
David | Capricorn | f
David | goat | f
David | Lamb | f
David | Tiger | t
David | wolf | t
David | Wolf | t
Yossi | Capricorn | f
Yossi | goat | f
This the query i've got so far (which returns the TABLE above):
SELECT
worker.wname, animal.type, animal.wild
FROM resposibility
LEFT JOIN worker ON resposibility.wid = worker.wid
LEFT JOIN cage ON resposibility.cno = cage.cno
LEFT JOIN animal ON cage.cno = animal.cno
GROUP BY worker.wname, animal.wild, animal.type
ORDER BY worker.wname
SELECT worker.wname
FROM resposibility
LEFT JOIN worker ON resposibility.wid = worker.wid
LEFT JOIN cage ON resposibility.cno = cage.cno
LEFT JOIN animal ON cage.cno = animal.cno
GROUP BY worker.wname
HAVING sum(case when animal.wild = 't' then 1 else 0 end) = 0
ORDER BY worker.wname
You only need table worker and the simplest is to use the NOT IN operator:
SELECT DISTINCT wname
FROM resposibility
WHERE wname NOT IN (SELECT wname FROM resposibility WHERE wild='t')
ORDER BY wname
You could also use the bool_or as follow:
SELECT worker.wname
FROM resposibility
LEFT JOIN worker ON resposibility.wid = worker.wid
LEFT JOIN cage ON resposibility.cno = cage.cno
LEFT JOIN animal ON cage.cno = animal.cno
GROUP BY worker.wname
having bool_or(animal.type) is false
ORDER BY worker.wname