How can i simply return a left join's column values as a separate key in a query?
SELECT meta.*
, post.* as venue
, venue_meta.* as venue_meta
FROM $wpdb->postmeta as meta
LEFT
JOIN $wpdb->posts as post
ON meta.meta_key = '_EventVenueID'
AND meta.meta_value = post.id
LEFT
JOIN $wpdb->postmeta as venue_meta
ON venue_meta.post_id = venue.id
WHERE meta.post_id = %d
GROUP
BY meta.meta_id
So i'm expecting all the columns in the post table to return as $response['venue'], but I have a syntax error on the first line.
Basically, a construct like post.* as venue isn't valid and produces the syntax error.
You can use one alias for one column name like post.id as id
But you will never get nested results for joins. The select will retrieve rows, which consist of a vector of columns with their values.
The short form of your query then would be
SELECT *
FROM $wpdb->postmeta as meta
LEFT
JOIN $wpdb->posts as post
ON meta.meta_key = '_EventVenueID'
AND meta.meta_value = post.id
LEFT
JOIN $wpdb->postmeta as venue_meta
ON venue_meta.post_id = venue.id
WHERE meta.post_id = %d
which would give you all the columns from all tables in one row (or array in PHP).
To split that into sub-arrays, the result-set let's you iterate over the result-sets properties like columns names and table names. This might help to build up the sub-arrays programmatically.
Related
I have the following MySQL query:
SELECT p.*,
IF(COUNT(ms.PropertyID) > 0,1,0) AS Contacted,
pm.MediaID,
date_format(p.AvailableFrom, '%d %b %Y') AS 'AvailableFrom',
astext(pg.Geometry) AS Geometry
FROM property p, propertygeometry pg
JOIN shortlist sl ON sl.PropertyID = p.id AND sl.MemberID = 384216
LEFT JOIN message ms ON ms.PropertyID = p.id AND ms.SenderID = 384216
LEFT JOIN property_media pm ON pm.PropertyID = p.id AND pm.IsPrimary = 1
WHERE p.paused = 0
AND p.PropertyGeometryID = pg.id
GROUP BY p.id
And I'm getting this error:
#1054 - Unknown column 'p.id' in 'on clause'
As far as I can see the query looks right, any idea what could be wrong?
Don't mix ANSI-89 style and ANSI-92 style joins. They have different precedence which can lead to confusing errors, and that is what has happened here. Your query is being interpreted as follows:
FROM property p, (
propertygeometry pg
JOIN shortlist sl ON sl.PropertyID = p.id AND sl.MemberID = 384216
...
)
In the above, the joins using the JOIN keyword are evaluated first before the comma-style join is even considered. At that point the table p isn't yet declared.
From the MySQL manual:
However, the precedence of the comma operator is less than of INNER JOIN, CROSS JOIN, LEFT JOIN, and so on. If you mix comma joins with the other join types when there is a join condition, an error of the form Unknown column 'col_name' in 'on clause' may occur. Information about dealing with this problem is given later in this section.
I'd recommend always using ANSI-92 style joins, i.e. using the JOIN keyword:
SELECT p.*,
IF(COUNT(ms.PropertyID) > 0,1,0) AS Contacted,
pm.MediaID,
date_format(p.AvailableFrom, '%d %b %Y') AS 'AvailableFrom',
astext(pg.Geometry) AS Geometry
FROM property p
JOIN propertygeometry pg ON p.PropertyGeometryID = pg.id
JOIN shortlist sl ON sl.PropertyID = p.id AND sl.MemberID = 384216
LEFT JOIN message ms ON ms.PropertyID = p.id AND ms.SenderID = 384216
LEFT JOIN property_media pm ON pm.PropertyID = p.id AND pm.IsPrimary = 1
WHERE p.paused = 0
GROUP BY p.id
Related:
Why isn't SQL ANSI-92 standard better adopted over ANSI-89?
As stated before there is a precedence issue using joins via the comma operator where the LEFT JOIN will be executed and so references to table aliases won't exist at that time. Though you can implicitly tell MySQL to use a JOIN via that statement you may also tell MySQL to evaluate the comma joined tables first, then execute left join thusly:
SELECT p.*,
IF(COUNT(ms.PropertyID) > 0,1,0) AS Contacted,
pm.MediaID,
date_format(p.AvailableFrom, '%d %b %Y') AS 'AvailableFrom',
astext(pg.Geometry) AS Geometry
FROM (property p, propertygeometry pg)
JOIN shortlist sl ON sl.PropertyID = p.id AND sl.MemberID = 384216
LEFT JOIN message ms ON ms.PropertyID = p.id AND ms.SenderID = 384216
LEFT JOIN property_media pm ON pm.PropertyID = p.id AND pm.IsPrimary = 1
WHERE p.paused = 0
AND p.PropertyGeometryID = pg.id
GROUP BY p.id
Notice the comma separated tables are contained within parenthesis (). The table aliases and columns will now be available to your other JOINs.
I bumped into this error unknown column, the diff is the query is built thru HQL inside session.executeQuery("select id, name, sum(paid), custType from cust group by brand") that's why having to manually type inner join or join keyword is not an option as the hql is the one generating it.
it produces a query sumthing like this:
select cust_id, name, sum(paid), c.custTypeId
from customer c, custType ct
on c.custTypeId = ct.custTypeId
it says "unknown c.custTypeId" column when I am 101% sure it bears that column.
My classes/relations:
Customer {
Integer custId
CustomerType custType
}
CustomerType{
Integer custTypeId
string code
}
the problem lies in the comma in "from customer, custType" line. it should be with the word JOIN as the answer stated above. but since it is HQL and is being generated, I can't do that. What I did is modified by query and instead of typing select custType, I typed select custType.id, custType.code
I know it's basic but for first timers like me, it was a struggle.
If this helps someone (and a note to future myself), I was getting this error when trying to execute the following queries in MariaDB:
SELECT a.name, b.name
FROM `cities` as a
INNER JOIN `countries` as b
ON `a.country_id` = `b`.`id`;
whereas I should have written it like:
SELECT a.name, b.name
FROM `cities` as a
INNER JOIN `countries` as b
ON `a`.`country_id` = `b`.`id`;
I'll leave it to the reader to spot the difference as an exercise. :)
I have used WPAllImport to import data from a CSV-file to Advanced Custom Fields.
I now want to put them back together with a SQL query, but dont know how to do it.
I've tried WPDataTables, but when I choose 5 or more tables, WPDataTables stops.
If I pick 2, I get this code
SELECT posts_podukter.post_title AS podukter_post_title,
podukter_meta_produkter_0_pris_tbl.meta_value AS podukter_meta_produkter_0_pris
FROM beta_h3L_posts AS posts_podukter
INNER JOIN (SELECT podukter_meta_produkter_0_pris_tbl_posts.ID as id, meta_value, meta_key FROM beta_h3L_postmeta AS podukter_meta_produkter_0_pris_tbl_postmeta INNER JOIN beta_h3L_posts AS podukter_meta_produkter_0_pris_tbl_posts ON podukter_meta_produkter_0_pris_tbl_postmeta.post_id = podukter_meta_produkter_0_pris_tbl_posts.ID AND podukter_meta_produkter_0_pris_tbl_posts.post_type = 'podukter') AS podukter_meta_produkter_0_pris_tbl
ON podukter_meta_produkter_0_pris_tbl.meta_key = 'produkter_0_pris' AND podukter_meta_produkter_0_pris_tbl.id = posts_podukter.ID
WHERE 1=1
AND posts_podukter.post_type = 'podukter'
I think this is too much code.
Can someone help me to get on the right way.... :-)
This is what the table should look like
Here is a capture how the table should look like
I would agree that this is "too much code" which sounds sort of ridiculous, but in this case totally applies. That SQL statement that was produced could be written as:
SELECT
post.post_title as podukter_post_title,
postmeta.meta_value as podukter_meta_produkter_0_pris
FROM beta_h3L_posts AS posts
INNER JOIN beta_h3L_postmeta AS postmeta
ON postmeta.post_id = post.ID
AND postmeta.meta_key = 'produkter_0_pris'
WHERE posts.post_type = 'podukter'
If there is another metavalue that you need you can join again to your meta table:
SELECT
post.post_title as podukter_post_title,
postmeta.meta_value as podukter_meta_produkter_0_pris,
postmeta2.meta_value as tilbudspris
FROM beta_h3L_posts AS posts
INNER JOIN beta_h3L_postmeta AS postmeta
ON postmeta.post_id = post.ID
AND postmeta.meta_key = 'produkter_0_pris'
INNER JOIN beta_h3L_postmeta AS postmeta2
ON postmeta.post_id = post.ID
AND postmeta2.meta_key = 'tilbudspris'
WHERE posts.post_type = 'podukter'
I don't know what any of these words mean (besides post and postmeta) so I'm just going to assume that this is right/helpful.
The only thing is that you may want to switch to using a LEFT OUTER JOIN to your postmeta table just in case the meta_key you are after doesn't exist for the post.id you are querying. In that case, with an INNER JOIN the id/post will be dropped from the result set where a LEFT OUTER JOIN will show the id/post record with a blank for whatever that corresponding meta_value is that you are joining in.
I'm trying to select Posts with the associate numbers of Comments and Likes.
This is my query
SELECT `waller_posts`.*,
COUNT(waller_comments.id) AS num_comments,
COUNT(waller_likes.id) AS num_likes
FROM `waller_posts`
LEFT JOIN `waller_comments` ON `waller_comments`.`post_id` = `waller_posts`.`id`
LEFT JOIN `waller_likes` ON `waller_likes`.`post_id` = `waller_posts`.`id`
WHERE `wall_id` = 1
AND `wall_type` = "User"
GROUP BY `waller_posts`.`id`
When I add the second left join in this case of the likes, the results of the num_comments and num_likes came wrong. How can I perform this kind of query?
The query builds up to give you every possible combination of comments and likes on a post.
Probably easiest to just use COUNT(DISTINCT...) :-
SELECT `waller_posts`.*,
COUNT(DISTINCT waller_comments.id) AS num_comments,
COUNT(DISTINCT waller_likes.id) AS num_likes
FROM `waller_posts`
LEFT JOIN `waller_comments` ON `waller_comments`.`post_id` = `waller_posts`.`id`
LEFT JOIN `waller_likes` ON `waller_likes`.`post_id` = `waller_posts`.`id`
WHERE `wall_id` = 1
AND `wall_type` = "User"
GROUP BY `waller_posts`.`id`
Note that your query is relying on a feature of MySQL but which would cause an error in most flavours of SQL. For most flavours of SQL you need to list ALL the non aggregate columns in the GROUP BY clause.
Use Distinct clause because it will display combination of like and comment table data
SELECT `waller_posts`.*,
COUNT(DISTINCT waller_comments.id) AS num_comments,
COUNT(DISTINCT waller_likes.id) AS num_likes
FROM `waller_posts`
LEFT JOIN `waller_comments` ON `waller_comments`.`post_id` = `waller_posts`.`id`
LEFT JOIN `waller_likes` ON `waller_likes`.`post_id` = `waller_posts`.`id`
WHERE `wall_id` = 1
AND `wall_type` = "User"
GROUP BY `waller_posts`.`id`
I will try to explain things as much as I can.
I have following query to fetch records from different tables.
SELECT
p.p_name,
p.id,
cat.cat_name,
p.property_type,
p.p_type,
p.address,
c.client_name,
p.price,
GROUP_CONCAT(pr.price) AS c_price,
pd.land_area,
pd.land_area_rp,
p.tagline,
p.map_location,
r.id,
p.status,
co.country_name,
p.`show`,
u.name,
p.created_date,
p.updated_dt,
o.type_id,
p.furnished,
p.expiry_date
FROM
property p
LEFT OUTER JOIN region AS r
ON p.district_id = r.id
LEFT OUTER JOIN country AS co
ON p.country_id = co.country_id
LEFT OUTER JOIN property_category AS cat
ON p.cat_id = cat.id
LEFT OUTER JOIN property_area_details AS pd
ON p.id = pd.property_id
LEFT OUTER JOIN sc_clients AS c
ON p.client_id = c.client_id
LEFT OUTER JOIN admin AS u
ON p.adminid = u.id
LEFT OUTER JOIN sc_property_orientation_type AS o
ON p.orientation_type = o.type_id
LEFT OUTER JOIN property_amenities_details AS pad
ON p.id = pad.property_id
LEFT OUTER JOIN sc_commercial_property_price AS pr
ON p.id = pr.property_id
WHERE p.id > 0
AND (
p.created_date > DATE_SUB(NOW(), INTERVAL 1 YEAR)
OR p.updated_dt > DATE_SUB(NOW(), INTERVAL 1 YEAR)
)
AND p.p_type = 'sale'
everything works fine if I exclude GROUP_CONCAT(pr.price) AS c_price, from above query. But when I include this it just gives one result. My intention to use group concat above is to fetch comma separated price from table sc_commercial_property_price that matches the property id in this case p.id. If the records for property exist in sc_commercial_property_price then fetch them in comma separated form along with other records. If not it should return blank. What m I doing wrong here?
I will try to explain again if my problem is not clear. Thanks in advance
The GROUP_CONCAT is an aggregation function. When you include it, you are telling SQL that there is an aggregation. Without a GROUP BY, only one row is returns, as in:
select count(*)
from table
The query that you have is acceptable syntax in MySQL but not in any other database. The query does not automatically group by the columns with no functions. Instead, it returns an arbitrary value. You could imagine a function ANY, so you query is:
select any(p.p_name) as p_num, any(p.tagline) as tagline, . . .
To fix this, put all your current variables in a group by clause:
GROUP BY
p.p_name,
p.id,
cat.cat_name,
p.property_type,
p.p_type,
p.address,
c.client_name,
p.price,
pd.land_area,
pd.land_area_rp,
p.tagline,
p.map_location,
r.id,
p.status,
co.country_name,
p.`show`,
u.name,
p.created_date,
p.updated_dt,
o.type_id,
p.furnished,
p.expiry_date
Most people who write SQL think it is good form to include all the group by variables in the group by clause, even though MySQL does not necessarily require this.
Add GROUP BY clause enumerating whatever you intend to have separate rows for. What happens now is that it picks some value for each result column and group_concats every pr.price.
I have a litte problem with a mysql query.
I use 5 tables:
user_has_data (uid, dataid); users (uid, uname); user_in_group(uid, groupid, data); groups(groupid, data, packageid); packages(packageid, name)
all ids are PK. I want to build a sql query that finds a user, which belongs to a specified dataid, by its uname and checks if the user is in a group (relation in table user_in_group) belonging to a specified package (a group is assigned to one package). if so data from users, package and group should be fetched, otherwise only the user data should be fetched. Therefore I use left joins, so I can also get the users with no group:
SELECT `uac`.`uid`, `u`.`uid`, `uig`.`groupid`, `ag`.`packageid`
FROM `user_has_data` AS `uac`
INNER JOIN `users` AS `u` ON u.uid = uac.uid
LEFT JOIN `user_in_group` AS `uig` ON uig.uid = uac.uid
LEFT JOIN `groups` AS `ag` ON (ag.groupid = uig.groupid) AND (ag.packageid = 2)
WHERE (uac.dataid = '3') AND (u.uname LIKE 'test%')
GROUP BY `u`.`uid`
Unfortunately I get wrong results: I get groups that have a different packageid than stated in the join, if the user has another group assigned to him with a different packageid.
probably this is because the first left join has no restrictions to packageid and the second is a left join and so it has no restrictions on the result (packageid is NULL for all results, but should have values). If I change the second left join to a ordinary join, the group problem would be fixed but the query cant find users without group any more.
Any ideas how to fix this or even possible?
thanks in advance!
Are you saying that you are actually seeing the value ag.packageid = 2 in your query results?
If not, I think you might try something like:
SELECT `uac`.`uid`, `u`.`uid`, `g`.`groupid`, `g`.`packageid`
FROM `user_has_data` AS `uac`
INNER JOIN `users` AS `u` ON u.uid = uac.uid
LEFT JOIN (`user_in_group` AS `uig`
INNER JOIN `groups` AS `ag` ON (ag.groupid = uig.groupid) AND (ag.packageid = 2) )
AS `g` ON uac.uid = g.uid
WHERE (uac.dataid = '3') AND (u.uname LIKE 'test%')
GROUP BY `u`.`uid`
Because you are limiting your search to a specific group packageid of '2', why not just make both of your LEFT JOIN INNER JOINS and then throw in ag.packageid = 2 in your WHERE clause?
SELECT `uac`.`uid`, `u`.`uid`, `uig`.`groupid`, `ag`.`packageid`
FROM `user_has_data` AS `uac`
INNER JOIN `users` AS `u` ON u.uid = uac.uid
LEFT OUTER JOIN `user_in_group` AS `uig` ON uig.uid = uac.uid
LEFT OUTER JOIN `groups` AS `ag` ON ag.groupid = uig.groupid
WHERE (uac.dataid = '3') AND (u.uname LIKE 'test%')
AND (ag.packageid = 2 OR uig.uid IS NULL)
GROUP BY `u`.`uid`
I know LEFT JOIN and LEFT OUTER JOIN mean the same thing, but I like to be explicit. With the condition in your join, I bet you were getting groups with different packages, but weren't getting the packages?