I have a query of a mysql database that joins two tables. In the first table it just pulls records based on an id. For the second table, there may or may not be matches based on a value in the first table. I want to get matches if there are any, otherwise, presumably those values of the resulting record set are empty.
The query seems to produce the right number of records. However, when I try to access values of some variables that should be present, I am not getting anything, either because I may be calling them the wrong name or they are not in recordset somehow. I am a bit fuzzy on mysql queries so would greatly appreciate any advice..
Table 1 parks
id | name | stateid
Table 2 parksvisited
id | visited | parkid | userid
PHP script
$sql = "SELECT *
FROM `parks` p
LEFT JOIN `parksvisited` pv
ON p.id = pv.parkid
WHERE p.stateid = '44'"
run query...
while($row = mysql_fetch_array($res))
{
if ($row['visited'] == 1) {
$visited = 1; }
else {
$visited = 0; }
Visited
}
Basically, I get stateid but I am not getting p.id or visited. It could be I am naming them wrong or possibly they are getting left out of results somehow... Thanks for any suggestions.
p.id is probably missing because each of p.id and pv.id are going to get returned as id, not as p.id or pv.id. Try this instead:
SELECT p.id pid,
p.*,
pv.id pvid,
pv.*
FROM `parks` p
LEFT JOIN `parksvisited` pv
ON p.id = pv.parkid
WHERE p.stateid = '44'
It also doesn't look like you're selecting anything from pv in your original query, just p. See if this new query takes care of visited as well. And make sure to refer to pid as $row['pid'], not $row['p.id'].
Related
So I have a query that gives me three numbers, I then want to look up these numbers from another table and get the name and url associated with them.
So I have a products table that i query, and that provides me these three numbers, but as there are 3 numbers, an inner join wouldnt work.
So I am essentially just trying to look up the name and url, of 3 numbers from the same table, and wondering how the most efficient way to achieve this would be.
$qry = mysqli_query($this->con,"SELECT * FROM products WHERE product_id=$this->id");
$row = mysqli_fetch_assoc($qry);
$main = $row['main_id'];
$cat = $row['categories_id'];
$sub = $row['sub_cat_id'];
So I can do a query for each number individually, but then that is a total of 4 queries. I was wondering if this could be done in just one, or possibly even 2.
Hard to say for sure without seeing some table structure and sample data, but something like this may work (where othertable is the name of the other table you are pulling urls and names from):
select p.mail_id,
p.categories_id,
p.sub_cat_id,
o1.url mail_id_url,
o1.name mail_id_name,
o2.url categories_id_url,
o2.name categories_id_name,
o3.url sub_cat_id_url,
o3.name sub_cat_id_name
from products p
join othertable o1 on o1.mail_id = p.mail_id
join othertable o2 on o2.categories_id = p.categories_id
join othertable o3 on o3.sub_cat_id = p.sub_cat_id
where p.product_id = $this->id
This assumes that a record exits in othertable for every id that you are looking up.
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.
I have two tables, Table A and Table B. For each record in table A there are many records in Table B; thus, a one to many relationship exists between tables A and B. I want to perform a query so that for each row returned from table A, all of the corresponding rows will be returned from table B. From what I understand I'll need to use a INNER Join - however, how would I go about accessing all of the returned rows through say, PHP?
$sql = "Select A.ID, B.Name * From A INNER JOIN B ON A.ID = B.ID";
A.ID | B.fName | B.lName
1 nameone lnameone
1 nametwo lnametwo
2 namethree lnamethree
4 namefour lnamefour
Now that I have the above results, I want to use PHP to loop through all of the values of B.Name only for a single A.ID at a time. So, the results I want would look like:
1.
nameOne lNameOne
nameTwo lnametwo
2. namethree lNamethree
4. nameFour lNameFour
Basically, I'm trying to group the query results by the ID in table A.
I appreciate the help very much!
Thank you,
Evan
You could just Google "php get from database," and use some normal array pre-processing, but I worry the advice you find may not be ideal. Here's what I'd do:
$pdo = new PDO('mysql:host=host;dbname=dbname', 'user', 'pass');
$result = $pdo->query(<<<SQL
SELECT
ID,
Name
FROM
A
-- Alternative to `JOIN B USING(ID)` or `JOIN B ON (A.ID = B.ID)
NATURAL JOIN B
SQL
);
$a = array();
while ($row = $result->fetch()) {
if (!isset($a[$row['ID']]) {
$a[$row['ID']] = array();
}
$a[$row['ID']][] = $row['Name'];
}
You could also GROUP BY the ID and GROUP_CONCAT the names to be exploded in PHP later to skip the manual array creation and reduce some iteration (although SQL will do more in that case).
Adding a simple ORDER BY A.ID to the SQL query would probably get you quite far in "grouping" the items together. It's difficult to give a more detailed answer without knowing exactly what you want to do with the "groups".
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
I'm trying to join two tables. The first table has a list of 11 items which are 'site_names' with an auto id field of 'id'. The second table that I want to connect has an auto id field of 'desc_id' and another field of 'descriptions'. This second table currently has 3 rows of data that I want displayed only for id 1 in table 1.
So, I want to accomplish is to connect the first site in table one with an id of '1' to the entire second table.
I can't seem to figure out how connect only the first entry(id=1) in table 1 to all the rows in table 2 (tb.1->id->1 to tbl.2->desc_id->1,2,3).
I hope that made sense. Any help would be great. Thanks
Try:
select site_name, descriptions
from table_1
inner join table_2
on 1 = 1
where table_1.site_id = 1
This should join give you what you want.
OK - based on the comment, I'm guessing what you want is:
site1 | desc1 | desc2 | desc3
all on one row. This is a bit trickier - particularly if you want it to remain open to an arbitrary number of descriptions. For just 3 (or, really, any limited subset, but as the number goes up, it gets ugly), you could do:
select site_name, t2.desc, t3.desc, t4.desc
from table_1
inner join table_2 t2
on t2.desc_id = 1
inner join table_2 t3
on t3.desc_id = 2
inner join table_2 t4
on t4.desc_id = 3
where site_id = 1
This kind of stuff is highly irregular though. It seems to me like something about your schema is probably not quite right to generate this sort of requirement.
Here is the query:
<?php
$mysql = new mysqli('localhost', 'root', 'root') or die('counld not connect');
$result = $mysql->query("SELECT ajax_demo.explore.site_name, anthony1.property.descriptions FROM ajax_demo.explore INNER JOIN anthony1.property ON ajax_demo.explore.id = anthony1.property.desc_id") or die($mysql->error);
if($result)
{
while($row = $result->fetch_object())
{
$id = $row->id;
$siteName = $row->site_name;
$siteDescription = $row->site_description;
echo "$siteName";
echo "$siteDescription";
}
}
?>
I may be missing something here, but it sounds to me like you need to add a foreign key to the Site table. If I understand your question correctly, your tables should look something like this:
Site
- SiteID
- DescriptionID
- SiteName
Description
- DescriptionID
- Description
Then your query to get Sites and their associated Descriptions would look like this:
SELECT
s.SiteName,
d.Description
FROM
Site s INNER JOIN Description d
ON s.DescriptionID = d.DescriptionID
This table structure assumes that multiple Sites share single Descriptions (as per your posted question).