I have a query thats joining two table, using the GROUP_CONCAT to get a comma separated list which is then being mapped to an array in an object
SQL:
$sql = "SELECT *,
GROUP_CONCAT(climb_attributes.attribute_id) as climb_attributes
FROM climbs
LEFT JOIN climb_attributes ON
(climbs.id = climb_attributes.climb_id)
GROUP BY climb_id
ORDER BY climbs.id";
PHP
$all_climb_profiles[$climb->id]->attributes = explode(",", $climb->climb_attributes);
Nearly working perfectly, except I currently only get back results IF the climb_attributes table contains the climb id. Essentially a climb can still exist even if it doesn't have any attributes, but at the moment it has to have an attribute to be returned in the results.
I also need to join it to another table to get the attribute name for the attribute id...if you can help with that as well that would be great, I'm hoping I can figure that out though.
First, you should not be using * to select from all tables when using group by. You can safely take all the columns from the climb table.
The problem is that you are aggregating on a column in the second table, rather than the first. And, it is NULL if there is no match. So, a better query is:
SELECT c.*, GROUP_CONCAT(ca.attribute_id) as climb_attributes
FROM climbs c LEFT JOIN
climb_attributes ca
ON c.id = ca.climb_id
GROUP BY c.id
ORDER BY c.id;
EDIT:
If you want to list the strings, then something like this should work:
SELECT c.*, GROUP_CONCAT(a.name) as climb_attributes
FROM climbs c LEFT JOIN
climb_attributes ca
ON c.id = ca.climb_id LEFT JOIN
attributes a
ON ca.attribute_id = c.id
GROUP BY c.id
ORDER BY c.id
Related
I have three tables
Products
id, name, desc
Flags
id, name
Product_flags
Product_id, Flag_id
Some Products have Flags linked to them while others not. I need select products and to give preferences to specific Flags in the select query.
This is my query to give preferences to flag ids 2,3,9, followed by other flags, and followed by non-flagged products ..
SELECT p.*, f.name flagname FROM products p
LEFT JOIN products_flags pf ON pf.product_id=p.id
LEFT JOIN flags f ON f.id = pf.flag_id
ORDER BY f.id=2, f.id=3, f.id=9, f.id, p.name
This sort order is not valid. How do I get it right?
Thanks
It's a strange request, but I think you might be able to get around it with a case statement in your order by clause like this:
SELECT
p.*, f.name flagname
FROM products p
LEFT JOIN products_flags pf ON pf.product_id=p.id
LEFT JOIN flags f ON f.id = pf.flag_id
ORDER BY
case
when f.id=2 then f.id-10
when f.id=3 then f.id-10
when f.id=9 then f.id-10
default f.id
end,
p.name
Edit: A column to order by might be a good idea when you want "funky" ordering. As for the case statement, what it does is returns a value to sort by but does so in this manner - sort of like an if statement:
if id=2 then treat it like -8
if id=3 then treat it like -7
if id=3 then treat it like -1
otherwise just use whatever is in id
I have three different SQL tables I need to join:
table "internet" with columns id|type|status
table "type_list" with columns id|type_name
table "status_list" with columns id|status_name
I want to output text from the two other tables (type_list, status_list) but not values as numbers which currently I have in table "internet".
I also don't want to make lazy programming - PHP array to make ID's equal to something like
$type_list = array("1"=>"VDSL2","2"=>"ADSL");
$status_list = array("1"=>"Pending","2"=>"Active");
because the text is already in the tables, i just dont know how to join them and output the text as query combined together in one query.
Use JOIN
SELECT i.id, type_name, status_name
FROM internet i
LEFT OUTER JOIN type_list t ON t.id = i.type
LEFT OUTER JOIN status_list s ON s.id= i.status
Read the MySQL doc for more informations.
Just write the select with the fields you want.
select internet.id,type_name,status_name from internet
inner join type_list
on type_list.id=internet.id
inner join status_list
on status_list.id=internet.id
For this you need a LEFT JOIN, like so:
SELECT i.id, t.type_name, s.status_name
FROM internet AS i
LEFT JOIN type_list AS t ON t.id = i.id
LEFT JOIN status_list AS s ON s.id= i.id
From your question, it is unclear what field you would like to join the queries on. In the above example, the queries are joined on the id field.
Please also note that the AS is not actually necessary, I have just put it in there to make it clear what is going on
I am try to get a count of all missing translations and getting really lost in how to do it.
Tables:
languages (language_id, name)
products (product_id)
product_translations (product_id, language_id, name)
The admin are getting very lazy and I want to be able to show them a count of how many translations are missing.
I guess a very simple was of doing this would be to just get the total (languages->count * products->count) but I wanted to return a count for each product separately.
To do such a query, start with a driver table (subquery) that has all combinations. Then remove the ones that have translations:
select driver.*
from (select distinct l.language_id, p.product_id
from languages l cross join
products p
) driver left outer join
translations t
on t.language_id = driver.language_id and
t.product_id = driver.product_id
where t.language_id is null;
This uses a left outer join, which keeps everything in the driver table. If there is no match, then the columns in translations will be NULL -- the where clause keeps only these.
The distinct may not be necessary in the subquery, if the values in each table are unique.
As a note: the above is my preferred way to write the query, because I think it is the clearest in intent. But, MySQL actually materializes the subquery. So the following is more efficient, if the columns are unique in the two reference tables:
select l.*, p.*
from languages l cross join
products p left outer join
translations t
on t.language_id = l.language_id and
t.product_id = p.product_id
where t.language_id is null;
I am building a blog with Codeigniter and MySQL. The question I have is this, I have a table with posts and one with categories. I also have a cross reference table with post_categories. What I am trying to do is get all the categories with their names and the number of posts they have under their name.
Example output would be: Hello World(1) Test(0) etc.
What I am having a hard time finding is a SQL query that will join the three tables and get me the counts, and I am also having a hard time wrapping my head around how to make that query.
Here is my table schema:
blgpost
====
id
*Other schema unimportant
blgpostcategories
=================
postid
categoryid
blgcategories
==========
id
name
*Other schema unimportant
This should give you the output you want....
SELECT c.name, COUNT(p.id) FROM
blgcategories c
INNER JOIN blgpostcategories pc ON c.id = pc.categoryid
INNER JOIN blgpost p ON pc.postid = p.id
GROUP BY c.id
You don't need to join the three tables - the blgpost table doesn't have any information in it that you need.
SELECT COUNT(*), blgcategories.name
FROM blgcategories INNER JOIN blgpostcategories
ON blgcategories.id=blgpostcategories.categoryid
GROUP BY blgcategories.id;
SELECT name, COUNT(pc.id)
FROM blgcategories c
LEFT JOIN
blgpostcategories pc
ON pc.categoryid = c.id
GROUP BY
c.id
Using LEFT JOIN will show 0 for empty categories (those without posts linked to them) rather than omitting them.
I have 2 tables. For simplicities sake 'u' has the following columns
userid
divisionid
'd' has the following:
divisionid
name
I did not create this table, otherwise I would not have this problem. u.DIVISION can be NULL. d.DIVISION cannot.
Running the following creates the appropriate data, but it also filters out every single userid that has NULL for it's divisionid. Is there anyway to still show all the userid's regardless of their divisionid and if the divisionid is not null, to then display the name of the division?
"SELECT userid, d.NAME
FROM u,d
WHERE u.divisionid = d.divisionid
ORDER BY userid"
Use an outer join:
SELECT userid, d.NAME
FROM u
LEFT OUTER JOIN division d
ON u.divisionid = d.divisionid
ORDER BY userid
Using the Oracle or implied join syntax implies an INNER JOIN. An inner join eliminates records that don't meet the criteria.
An explicit join using the JOIN clause allows you to specify the type of join.
A LEFT OUTER JOIN keeps all rows in the first table, regardless if there are matching rows in the second table.
SELECT userid, d.NAME
FROM u
LEFT OUTER JOIN division d
ON d.divisionid = u.divisionid
ORDER BY userid