I am trying to make a "recipe" system inside a game. The player can own a company and craft items in there.
I currently fetch the recipes per company type but I don't know how to write the query in a way that I can also fetch the item names and images if the item_id is not empty.
This is working:
SELECT a.recipe_id,
a.item1_id,
a.item1_uses,
a.item2_id,
a.item2_uses,
a.item3_id,
a.item3_uses,
a.item4_id,
a.item4_uses,
a.item5_id,
a.item5_uses,
a.newitem_id,
a.newitem_uses,
a.craft_description,
a.craft_button
FROM
company_recipes AS a,
company_types AS b
WHERE
a.type_id = b.type_id
AND
b.type_id = '".$type."';
"
A recipe can contain for example two items needed to craft something new, but it could also be 5. So if it's only 2, I only want to fetch the img, name of these 2 and the rest can be skipped.
I have a different table store_items that contains the img and name of the item. I was thinking something along the lines of an IF ELSE or CASE WHEN inside the query, but I'm not sure how I'd do that.
Something like: SELECT c.img, c.name FROM store_items AS c IF a.item1_id is not NULL.
I feel like I'm close to the solution, but missing the last step.
Thanks for the tips #jarlh, I've changed the code and came to this result. If you have any more tips to do it better I'm happy to listen. (I'm still a junior and thought myself by trial and error, so I might not have the best solutions at times... Which is why tips are highly appreciated).
SELECT cr.recipe_id,
cr.item1_id,
cr.item1_uses,
si1.name,
si1.img,
cr.item2_id,
cr.item2_uses,
si2.name,
si2.img,
cr.item3_id,
cr.item3_uses,
si3.name,
si3.img,
cr.item4_id,
cr.item4_uses,
si4.name,
si4.img,
cr.item5_id,
cr.item5_uses,
si5.name,
si5.img,
cr.newitem_id,
cr.newitem_uses,
si_new.name,
si_new.img,
cr.craft_description,
cr.craft_button
FROM
company_recipes AS cr
INNER JOIN company_types AS ct ON cr.type_id = ct.type_id
LEFT JOIN store_items AS si1 ON cr.item1_id = si1.item_id
LEFT JOIN store_items AS si2 ON cr.item2_id = si2.item_id
LEFT JOIN store_items AS si3 ON cr.item3_id = si3.item_id
LEFT JOIN store_items AS si4 ON cr.item4_id = si4.item_id
LEFT JOIN store_items AS si5 ON cr.item5_id = si5.item_id
LEFT JOIN store_items AS si_new ON cr.newitem_id = si_new.item_id
WHERE
ct.type_id = '".$type."';
I'm basically fetching everything now and handle the NULLs in the php code now.
Without seeing more info its had to see what you are trying achieve but you could start by using the the users inpute of the game to determine what data is first required before futher filtering. Try this:
Declare #Value int
set #Value = #User_input --- uses what ever the game user will
SELECT
a.recipe_id,
a.item1_id,
a.item1_uses,
a.item2_id,
a.item2_uses,
a.item3_id,
a.item3_uses,
a.item4_id,
a.item4_uses,
a.item5_id,
a.item5_uses,
a.newitem_id,
a.newitem_uses,
a.craft_description,
a.craft_button
--- you can insert more columns but i stopped here as i dont know what data you have in the other tables.
FROM
company_recipes a
INNER JOIN company_types b ON a.type_id = b.type_id
INNER JOIN store_items c ON c.type_id = b.type_id
WHERE
b.type_id = #Value; --- '".$type."';
Related
I got the bellow piece of select statement that got level 2 child records, having problems to got deeper, can anyone help out?
SELECT
id_mobile AS ID_PROJETO,
UM.qtd_UC,
AM.qtd_AMBIENTE
FROM projetos_mobile AS PM
LEFT JOIN (
SELECT
COUNT(id) AS qtd_UC,
projeto,
data_hora_importacao,
id_uc_mobile
FROM ucs_mobile
WHERE data_hora_importacao = '2015-05-15 17:21:02'
GROUP BY projeto) AS UM
ON PM.id_mobile = UM.projeto
LEFT JOIN (
SELECT
COUNT(id_uc_mobile) AS qtd_AMBIENTE,
id_uc_mobile
FROM ucs_mobile
LEFT JOIN (
SELECT
uc
FROM ambientes_mobile AS s
WHERE data_hora_importacao = '2015-05-15 17:21:02') AS G
ON G.uc = ucs_mobile.id_uc_mobile
WHERE data_hora_importacao = '2015-05-15 17:21:02') AS AM
ON UM.id_uc_mobile = AM.id_uc_mobile
WHERE PM.data_hora_importacao = '2015-05-15 17:21:02'
http://sqlfiddle.com/#!9/2eecf
here is a sqlfiddle if anyone want to try a solution. I have the specific hierarchy: projeto>uc>ambiente>secao>medicoes
ucs_mobile.projeto refers to projetos_mobile.id_mobile
ambientes_mobile.uc refers to ucs_mobile.id_uc_mobile
secoes_iluminacao_mobile.ambiente refers to ambientes_mobile.id_ambiente_mobile
I need a count of each child for the parent I pass, I will have 5 functions that
return the count of each child for a given parent, for example, for a projeto parent I should have count(ucs),count(ambientes),count(secoes),count(medicoes)
So, hope you guys can help me. The database is terrible ugly but that's is what I got. Appreciate any help.
When you have really large queries like this, it can often be helpful to break them down individually, starting from the ground up and patching them together.
I started by just getting the count of each ucs_mobile row for each projetos_mobile value. You can do that by joining the two tables on the related row, and using COUNT(DISTINCT um.id) to get the number of rows. There are other ways to do it, but this particular method will scale better for the rest of your query:
SELECT pm.id, COALESCE(COUNT(DISTINCT um.id), 0) AS qty_uc
FROM projetos_mobile pm
LEFT JOIN ucs_mobile um ON um.data_hora_importacao = '2015-05-15 17:21:02' AND um.projeto = pm.id_mobile
GROUP BY pm.id;
The COALESCE function will be used to fill 0 counts. As long as you remember to use the DISTINCT keyword, and group by the proper id, you can just add in the child rows like so:
SELECT
pm.id,
COALESCE(COUNT(DISTINCT um.id), 0) AS qty_uc,
COALESCE(COUNT(DISTINCT am.id), 0) AS qty_am,
COALESCE(COUNT(DISTINCT sim.id), 0) AS qty_sim
FROM projetos_mobile pm
LEFT JOIN ucs_mobile um ON um.data_hora_importacao = '2015-05-15 17:21:02' AND um.projeto = pm.id_mobile
LEFT JOIN ambientes_mobile am ON am.data_hora_importacao = um.data_hora_importacao AND am.uc = um.id_uc_mobile
LEFT JOIN secoes_iluminacao_mobile sim ON sim.data_hora_importacao = am.data_hora_importacao AND sim.ambiente = am.id_ambiente_mobile
GROUP BY pm.id;
Here is an SQL Fiddle example. NOTE I changed your sample data slightly to ensure my query was working as expected.
Also, a side note. I noticed as you went along that you kept using the same date in your WHERE clauses, so I just joined each table on the date as well, and made sure that in my very first join I looked for the date specified, which in turn will carry its way over to the other tables.
$sql = 'SELECT *
FROM table_all ta
INNER JOIN table11 ta11
ON ta11.column1 = ta.column1
INNER JOIN table12 ta12
ON ta12.column2 = ta.column2
INNER JOIN table13 ta13
ON ta13.column3 = ta.column3';
This is a sql statement of a PHP-programm that I am currently working on. It works fine actually, but I am unsatisfied with the outcome of this statement. It would be nice to have
only the content of the table_all and then
only the three columns of those other three tables (table11, table12, table13).
The asterisk creates some problems in this regard.
The length of table_all is not known. It is able to change in size.
I tried Union and multiple selects, but only received errors. How would one deal with such a problem?
You can try specifying which columns do you want to get.
As you can see asterisk returns all columns.
You should use something like:
$sql = 'SELECT ta11.column1, taa12.column2, ta13.column13
FROM table_all ta
INNER JOIN table11 ta11
ON ta11.column1 = ta.column1
INNER JOIN table12 ta12
ON ta12.column2 = ta.column2
INNER JOIN table13 ta13
ON ta13.column3 = ta.column3';
I don't see a point in getting ta11.column1, taa12.column2, ta13.column13 because these fields are already in table_all (you use these columns in Join). But you can select any columns you want that way.
I am trying to learn about SQL joins and trying to apply them to an application I am building. I am doing a query to find a "game record" on a schedule based on a specific game id. But on this game record; for the "h_team" and the "v_team"; only the ids of the teams are on the game record. And so what I want to do is join the "teams" table and look up the two different team_names of the "h_team" and "v_team". I have it also pull in a "division name" as well using a join since only the division id is stored on the game record. I have gotten this all to work fine; except I do not know how to get the results separately for the "team_name" for h_team and v_team. Basically the key for each one is just "team_name"; I will paste in my code and then explain further:
$array_game_id6=32;
$sql = "SELECT * FROM playoff_schedule LEFT OUTER JOIN teams on playoff_schedule.h_team = teams.team_id || playoff_schedule.v_team = teams.team_id LEFT OUTER JOIN playoff_divisions on playoff_schedule.po_div_id = playoff_divisions.po_div_id WHERE tom_game_id=$array_game_id6";
foreach ($dbh->query($sql) as $resultsg39)
{
$h_team=$resultsg39[h_team];
$v_team=$resultsg39[v_team];
$po_div_id=$resultsg39[po_div_id];
$round=$resultsg39[round];
$game_id=$resultsg39[game_id];
$date=$resultsg39[date];
$timestamp=$resultsg39[timestamp];
$h_score=$resultsg39[h_score];
$v_score=$resultsg39[v_score];
$tom_game_id=$resultsg39[tom_game_id];
$h_name=$resultsg39[team_name];
$div_name=$resultsg39[playoff_name];
}
the problem comes in when i am trying to get the results of the query and store them all in the different variables…
the last two "$h_name" and "$div_name" are being pulled from the JOINs all the prior ones are on the game record itself…
what I want to do is store both the names from "v_team" and "h_team" in the respective variables $h_name and $v_name;
I have it storing the $h_name no problem; but i do not know how to make it store both $h_name and $v_name separately as they are both values in the column "team_name" from "teams" table. So I just need to somehow make it so when i get my results it can tell the difference between the two different "team_names" and I can store them in the two different variables…
If this is not clear please let me know.
Thanks!
***** UPDATE 10:49pm EST 2/5/2015
have made some progress on this but my query is not working; I think it is a problem with the aliases and such are not right; here is my non-working query as it is right now:
$sth = $dbh->prepare("SELECT home_team.team_name as home_team_name, visiting_team.team_name as visiting_team_name,
h_team, v_team, po_div_id, round, game_id, date, timestamp, h_score, v_score, tom_game_id, playoff_name FROM playoff_schedule
LEFT OUTER JOIN teams as home_team on playoff_schedule.h_team = teams.team_id
LEFT OUTER JOIN teams as visiting_team on playoff_schedule.v_team = teams.team_id
LEFT OUTER JOIN playoff_divisions on playoff_schedule.po_div_id = playoff_divisions.po_div_id
WHERE tom_game_id=$array_game_id6");
$sth->execute();
$article_list = $sth->fetchAll(PDO::FETCH_ASSOC);
foreach ($article_list as $row => $link) {
$h_team=$link['h_team'];
$v_team=$link['v_team'];
$po_div_id=$link['po_div_id'];
$round=$link['round'];
}
if anyone can spot a problem with my new query I would really appreciate it!
I think what you are trying to do is:
select home_team.team_name as home_team_name,
visiting_team.team_name as visiting_team_name
from playoff_schedule
join team as home_team on playoff_schedule.h_team = teams.team_id
join team as visiting_team on playoff_schedule.v_team = teams.team_id
You can join to the same table as many times as you want to. In this case, it makes sense, because you really are trying to get two different bits of information.
Based on your last edit, the following query appears to work:
SELECT home_team.team_name AS home_team_name,
visiting_team.team_name AS visiting_team_name,
h_team,
v_team,
playoff_schedule.po_div_id,
round,
game_id,
date,
timestamp,
h_score,
v_score,
tom_game_id,
playoff_name
FROM playoff_schedule
LEFT OUTER JOIN teams AS home_team
ON playoff_schedule.h_team = home_team.team_id
LEFT OUTER JOIN teams AS visiting_team
ON playoff_schedule.v_team = visiting_team.team_id
LEFT OUTER JOIN playoff_divisions
ON playoff_schedule.po_div_id = playoff_divisions.po_div_id
WHERE tom_game_id=$array_game_id6
You can check the query and the schema at: SQLFiddle
A couple of thing that might be happening:
Is the query itself running?
What happens if you run the query in a mySQL client?
Are there any PHP errors in your log?
Could you post the schema itself?
Is $array_game_id6 actually an array of values? In that case, you need to use "in" as opposed to "=" in your where clause.
With regard to your updated query, I think the main thing you are missing is using the aliases in your JOIN conditions. You should keep your table aliases consistent throughout your query. Also, IMO its better to keep table aliases short so they are easier to read:
So applying those things to your query:
SELECT h.team_name as h_team_name, v.team_name as v_team_name, s.h_team, s.v_team, s.po_div_id, s.round, s.game_id, s.date, s.timestamp, s.h_score, s.v_score, s.tom_game_id, s.playoff_name
FROM playoff_schedule s
LEFT OUTER JOIN teams h ON (
s.h_team = h.team_id
)
LEFT OUTER JOIN teams as v ON (
s.v_team = v.team_id
)
LEFT OUTER JOIN playoff_divisions d ON (
s.po_div_id = d.po_div_id
)
WHERE s.tom_game_id = ?
Now I'm not 100% sure of your schema so I may have referenced some of the columns to the wrong table but you should be able to sort that out.
I keep falling back into questions with MySQL joining.
And I would like to request a very simple example I could use to continue my journey of understanding learning the MySQL syntax.
Let's say I got the following table's
test_testtable
testtable_id
testtable_name
testtable_user
testtable_option
testtable_textfield
test_testlink
testlink_id
testlink_link
testlink_address
test_address
address_id
address_name
address_phone
address_email
address_street
address_city
address_zip
I would like to make a selection like :
SELECT * (lets say I would define the fields) FROM `test_testable`
JOIN `test_testtable`.`testtable_id` = `test_testlink`.`testlink_link`
AND
JOIN `test_testlink`.`testlink_addres` = `test_address`.`address_id`
WHERE `user_id` = 5
Hence the linking structure is like:
test_testtable.testtable_id = leading
table test_testlink is a table to link the table test_testtable and test_address
And linking table test_testlink uses the field testlink_link to link to the table test_testtable, and uses the field testlink_address to link to the table test_address
This does not work. FOR ME.. Since I continuously seem to fail of catching the correct syntax logic.
So I hope that someone could give me a small example of how to correctly implement such a simple yet critical query!
TIAD!!
A general approach :
SELECT table1.* FROM table1
JOIN table2 ON table2.id_table1 = table1.id
JOIN table3 ON table3.id_table2 = table2.id
WHERE table1.id = 10
For your purpose :
SELECT * (lets say I would define the fields) FROM `test_testable`
JOIN `test_testlink` ON `test_testtable`.`testtable_id` = `test_testlink`.`testlink_link`
JOIN `test_address` ON `test_testlink`.`testlink_addres` = `test_address`.`address_id`
WHERE `user_id` = 5
Please read the reference
You are using wrong syntax. You should mention which tables to join first then based on which fields.
SELECT * (lets say I would define the fields) FROM `test_testable`
INNER JOIN test_testlink
ON `test_testtable`.`testtable_id` = `test_testlink`.`testlink_link`
INNER JOIN `test_address`
ON `test_testlink`.`testlink_addres` = `test_address`.`address_id`
AND `test_testtable`.`user_id` = 5
select * from testlink JOIN testtable ON testlink.tableid = testtable.ID
JOIN testaddress ON testlink.addressid = testaddress.ID
WHERE testtable.ID = 5
I've been working on a project that until now has only needed to find 1 row from the joined table. But now I need to grab multiple rows..
So as it stand my sql works something like:
Select rows for each company for this particular project which alone would find company details (name, id, telephone.. blah).
Then I join a table that contains form data submitted for each company (multiple forms - so multiple records)
Until now i have been specifying one formid to look for in the join, but now i need to specify multiple ones.
If I use WHERE form_id = 1 OR form_id = 2 OR form_id = 3 ... I get a result of only the first form match that is found per company..
If I mix up the query so it looks for the forms 1st and returns multiple records for each company with different form data - that works in this sense..
But I am then looping through this array in a view and creating a table row per record (previously each row was a new company) but using the latter would cause multiple records to show for the same company.
Any way I can do this? I tried group by with the latter method but this results in only 1 record again.
SELECT DISTINCT p.project_company_has_user_id, p.project_company_has_user_project_id, p.project_company_has_user_user_id, c.company_id, c.company_hall_no, c.company_company_name, c.company_type, c.company_country, c.company_stand_number, c.company_image_file_1, p2.project_id, p2.project_name, u.user_id, u.user_username, o.orders_id, o2.order_detail_id, o2.order_detail_product_id, f2.form_question_has_answer_id, f2.form_question_has_answer_request, f2.form_question_has_answer_form_id, f2.form_question_has_answer_user_id
FROM project_company_has_user p
INNER JOIN company c ON p.project_company_has_user_company_id = c.company_id
INNER JOIN project p2 ON p.project_company_has_user_project_id = p2.project_id
INNER JOIN user u ON p.project_company_has_user_user_id = u.user_id
INNER JOIN form f ON p.project_company_has_user_project_id = f.form_project_id
LEFT JOIN orders o ON p.project_company_has_user_user_id = o.orders_user_id
LEFT JOIN order_detail o2 ON ((o2.order_detail_orders_id = o.orders_id AND (o2.order_detail_product_id = 65 OR o2.order_detail_product_id = 68 OR o2.order_detail_product_id = 64)))
LEFT JOIN form_question_has_answer f2 ON ((f2.form_question_has_answer_form_id = 297 AND f2.form_question_has_answer_user_id = p.project_company_has_user_user_id))
WHERE (f.form_template_name = "custom" AND p.project_company_has_user_garbage_collection = 0 AND p.project_company_has_user_project_id = 48) AND (LCASE(c.company_country) LIKE "%uk%" OR LCASE(c.company_country) LIKE "%uk%") ORDER BY company_company_name asc
you need another field in order_detail as o2 . this field is row_index(position),etc for positioning record
LEFT JOIN order_detail o2 ON (o2.row_index=1 AND (o2.order_detail_orders_id = o.orders_id AND (o2.order_detail_product_id = 65 OR o2.order_detail_product_id = 68 OR o2.order_detail_product_id = 64)))
Personally I would use an Outer Join for the table of which elements you need to list all matches. Should you them need to clean up that data you can build the logic into the Join Condition (as step 2). Depending on the volume of data you are handling and whether or not you need to reuse it later in the same proc, you may want to post that primary dataset into a temp table and use that as source (primary) for your later logic.
Hope that helps. If you need the code, let me know, but it is pretty straight forward.
Regards
Mac