mysql query with dynamic return column name - mysql

I have 3 tables,Products, Languages and Products_translation.
How can I retrieve one Product and all translation at same time in one query ?
I have this
SELECT p.*, pt.description FROM Products p
LEFT JOIN Products_translation pt ON p.id=pt.product_id
LEFT JOIN Languages l ON pt.language =l.code
I have 3 languages, but it only retrieves one field name 'description' and I wanted it to return 3 (the number of languages), with something like description_en, description_es, description_fr
It's possible to make something like pt.description AS 'description'+'l.code' ?

This is a very common question and I'm fairly sure it's been answered many times (for example here: Mysql: joining tables for translation records). Anyway, if you have only 3 languages, just do this:
SELECT p.*, pt_en.description as description_en, pt_es.description as description_es, pt_fr.description as description_fr FROM Products p
LEFT JOIN Products_translation pt_en ON (p.id=pt.product_id and pt.language = 'en')
LEFT JOIN Products_translation pt_es ON (p.id=pt.product_id and pt.language = 'es')
LEFT JOIN Products_translation pt_fr ON (p.id=pt.product_id and pt.language = 'fr')
If you have more than 3, or a varying number, search pivoting or pivot table for more info. It's not easy to do in SQL so usually it's faster to just select your products, select all the translations of those products in a separate query, and construct the result you want outside of the database.

Related

Master Product list from multiple tables with the exact same column names

I’ve got quite a few tables with product information. The columns on each table that I’m pulling from in this particular query have the exact same column names. I’ve been attempting to do it via a UNION ALL but for some reason it is throwing an error saying non-object but all the column names are correct.
I’m using a format that I found online. But obviously something is wrong. There are more tables; however, this is how it starts (with 2). I’d prefer not to have to code each select statement in the union with unique table abbreviations if I don’t have to.
I don’t have to use union if there is a better method.
All tables share data on Product_Categories and Product_Sub_Category.
The only thing unique to each table is id and part_number.
SELECT f.id,f.part_number,f.cat,f.subcat,f.table_name FROM
(
SELECT t.id,t.part_number,psc.name as subcat,c.name as cat, c.table_name FROM Steel_Strapping as t JOIN Product_Sub_Category as psc ON t.subcat = psc.id JOIN Product_Categories as c ON psc.category = c.id ORDER BY c.sort_order,psc.sort_order,t.sort_order
UNION ALL
SELECT t.id,t.part_number,psc.name as subcat,c.name as cat, c.table_name FROM Product as t JOIN Product_Sub_Category as psc ON t.subcat = psc.id JOIN Product_Categories as c ON psc.category = c.id ORDER BY c.sort_order,psc.sort_order,t.sort_order
) f
My end result is one full list of all products sharing column names. Ex: $result[‘part_number’] will pull part numbers from ALL tables listed in union.
I found the solution when playing around with code. I had to add parenthesis (select...) UNION JOIN (select...) inside the parent select statement

SQL Join with multiple conditions for one column

In my situation, I've two tables, a table with all institutions profile and a table which represents material studied by each of these institutions.
In a search, I want to look for institution's name which studied specifics type of material. So it's possible to look for institution which studied "Wood" and "Metal", just "Metal" etc...
I've tried the following query :
SELECT p.name
FROM q1_institution_profiles p
INNER JOIN q9_materials_studied_by_institution pf
ON pf.id_institution = p.id_institution
WHERE pf.id_material_studied = 10 AND pf.id_material_studied = 8
However result is empty because there is a problem when I have multiple conditions (here id_material_studied must be equal 8 and 10).
Is there a way to achieve this properly or do I have to do on join for each criteria ?
Thank you in advance for answer
I think this is what you want:
SELECT p.name
FROM q1_institution_profiles p INNER JOIN
q9_materials_studied_by_institution pf
ON pf.id_institution = p.id_institution
WHERE pf.id_material_studied IN (8, 10)
GROUP BY p.name
HAVING COUNT(DISTINCT pf.id_material_studied) = 2;
That is, get names where there are rows with each of the two values.
The WHERE clause selects only materials 8 and 10. The GROUP BY then groups these by p.name. The question is: Does a single name have both these materials? Well, that is what count(distinct) does.

Avoiding a MySql Loop With Query

I've got three tables.
Table 1 is packages.
Table 2 is package_to_keyword.
Table 3 is keywords.
Packages can be connected to multiple keywords. So if I query package_to_keyword Joining keywords and packages I can search for all packages that relate to a certain keyword. That's the part I understand.
NOW... my question is, how do I retrieve packages that match a LIST of keywords? Right now, in php, I loop a sql statement and then loop through all the results for each keyword and do an array_intersect() to filter down to the packages that show up in all the result sets. However, I'm sure this is bad, because I'm running a query for each keyword when I'm certain SQL is built to handle this type of relationship, I'm just not sure what type of query to perform.
The key is the list of keywords can be any number of words. If I use something like IN ('keyword','array','returns','all','results') I just get a list for all the packages that have a relationship with ANY of the keywords when I just want packages that have a relationship with ALL of the keywords.
Thoughts?
select title
from packages p
inner join pack_to_tag pt on p.index = pt.pIndex
inner join keyworks w on w.index = pt.kindex
where word in ('keyword','array','returns','all','results')
group by title
having count(*) = 5
First, the "PreQuery" (qualified products result) looks only the products joined to keywords that have ANY of the keywords you are looking for, and will ultimately return 1 or more entries. The GROUP BY then confirms however many you ARE EXPECTING... Then join to products for final results.
select
p.*
from
( select ptt.pIndex
from pack_to_tag ptt
join keywords k
on ptt.kindex = k.index
and k.word in ( 'word1', 'word2', 'word3' )
group by
ptt.pIndex
having
count(*) = 3 ) QualifiedProducts
join Products p
on QualifiedProducts.pIndex = p.index

MYSQL query issue - join product details into result

I want to get some data out of my database that is similar to a receipt you get at the supermarket (just an example which suits kinda good to my real situation).
For example you get the 2 (always only 2) products 1 and 3. These products are stored in a seperated product database.
Your shopping result is stored in one database containing all the details like time, location and so on AND in 2 columns (product_1, and product_2). Again this shopping situation is only a comparison to my real situation so I know that this would not be a good database structure for a shopping list.
So now I would like to get the Whole receipt but instead of printing the product IDs I would like to have the Name and for example the price on it.
If I had only one product I would use this query:
SELECT `list`.`time`, `list`.`location`, `prod`.`prod_name`, `prod`.`prod_price`
FROM `shopping_list` `list`, `products` `prod`
WHERE `list`.`product_1` = `prod`.`prod_id`
But since I have two products I cannot just go on with
AND `list`.`product_2` = `prod`.`prod_id`
But how do you achive what I would like to have?
Thank you very much,
Phil
You'll need to join to the product table twice
e.g.
SELECT
`list`.`time`,
`list`.`location`,
`prod1`.`prod_name` `prod_name1`,
`prod1`.`prod_price` `prod_price1` ,
`prod2`.`prod_name` `prod_name2`,
`prod2`.`prod_price` `prod_price2`
FROM `shopping_list` `list`
INNER JOIN `products` `prod1`
ON `list`.`product_1` = `prod1`.`prod_id`
INNER JOIN `products` `prod2`
ON `list`.`product_2` = `prod2`.`prod_id`
I'm not sure what your business rules are so you may need to convert the second INNER JOIN to a LEFT JOIN if they need to always select two products.
i don't know your exact situation but usually field names like product_1 and product_2 indicate bad database design. however if you really need that you need to join the products table twice.
select
*
from
list l
, product p1
, product p2
where
l.product_1 = p1.product_id
and l.product_2 = p2.product_id
(this is oracle syntax but i think it will work also in mysql).
hth.
The previous answers work well if you can parse out the two lines from 1 database result row. If you want two lines from the database you could do a UNION query:
SELECT `list`.`time`, `list`.`location`, `prod`.`prod_name`, `prod`.`prod_price`
FROM `shopping_list` `list`, `products` `prod`
WHERE `list`.`product_1` = `prod`.`prod_id`
UNION
SELECT `list`.`time`, `list`.`location`, `prod`.`prod_name`, `prod`.`prod_price`
FROM `shopping_list` `list`, `products` `prod`
WHERE `list`.`product_2` = `prod`.`prod_id`

MySQL dynamic JOIN

Let's say that I have these tables on my db:
items
categories
weapons
shields
swords
And I need to create a join like this:
SELECT items.*, {swords}.*
FROM items
INNER JOIN categories
ON categories.id = items.category_id # <-- here I know that the item is a sword
INNER JOIN {swords}
ON {swords}.item_id = item.id
WHERE items.id = 12
But the {swords} part is dynamic since I found that an item is a sword checkgin the categories.name field.
The query will change if the categories.name is "shield" to this:
SELECT items.*, shields.*
FROM items
INNER JOIN categories
ON categories.id = items.category_id
INNER JOIN shields
ON shields.item_id = item.id
WHERE items.id = 13
I used { and } around the swords to show it like a variable
Thank you for your answer and sorry about my english! :)
Technically, you can only do this with dynamic SQL - which means MySQL's Prepared Statement syntax, or string concatenation to create the query prior to submitting it to the database. Prepared Statements are the preferable choice, due to better SQL injection defense.
You could use LEFT JOINs to the various tables, but it would mean including numerous columns from each of the tables (weapons, shields, swords...) that would be null if the category didn't match. It'd be horrible to try to pull out data from a single query...
PS: Why is there a SWORD table? Wouldn't that be covered by the WEAPON table?