mysql group by partially - mysql

Hi I've written this code :
select `wp_term_taxonomy`.*, count(*)
from `wp_posts`
inner join `wp_term_relationships` on `wp_term_relationships`.`object_id` = `wp_posts`.`ID`
inner join `wp_term_taxonomy` on `wp_term_taxonomy`.`term_taxonomy_id` = `wp_term_relationships`.`term_taxonomy_id`
where `post_type` = 'product'
and exists(select *
from `wp_term_taxonomy`
inner join `wp_term_relationships` on `wp_term_taxonomy`.`term_taxonomy_id` = `wp_term_relationships`.`term_taxonomy_id`
where `wp_posts`.`ID` = `wp_term_relationships`.`object_id`
and `wp_term_taxonomy`.`term_taxonomy_id` in (401)
and `taxonomy` = 'product_cat')
and wp_posts.ID = wp_term_relationships.object_id
group by `wp_term_taxonomy`.`term_taxonomy_id`
So here is the result :
In taxonomy column every value is what I want except pa_shirt_size (at row 22 and 23), for pa_% items I want only one row of each no matter how many they are and which one gets chosen I just want one of each pa_shirt_size and one of pa_shirt_color and ..., basically one of each pa_% in taxonomy.How's this possible? (I don't want to use a seperate query.)

Test
GROUP BY CASE WHEN `wp_term_taxonomy`.`taxonomy` LIKE 'pa_%'
THEN `wp_term_taxonomy`.`taxonomy`
ELSE `wp_term_taxonomy`.`term_taxonomy_id`
END
ONLY_FULL_GROUP_BY SQL mode must be disabled. If not then use ANY_VALUE() or any other aggregate function(s).
Modelling DEMO

Related

SQL Inner Query WHERE clause access to Outer Query tables

Good morning -
This is my first post here, after many years using SO as a very useful resource.
I've run into a problem with a complex (for me) query I'm pulling together for a wordpress site running woocommerce to process orders. I'm trying to add a filter to the order list which filters orders which contain products in a particular product category.
I'm afraid I've gotten in over my head with this query which joins a variety of meta tables on inner queries in order to get at the information I need in order to determine the product's category.
The problem is that I can't get the scoping rules to work in order to access required outer table information in the inner queries.
The query is:
SELECT SQL_CALC_FOUND_ROWS
wp_ot6q6i_posts.ID
FROM
wp_ot6q6i_posts
WHERE
1 = 1 AND YEAR(wp_ot6q6i_posts.post_date) = 2015 AND MONTH(wp_ot6q6i_posts.post_date) = 12 AND wp_ot6q6i_posts.post_type = 'shop_order' AND(
(
wp_ot6q6i_posts.post_status = 'wc-pending' OR wp_ot6q6i_posts.post_status = 'wc-processing' OR wp_ot6q6i_posts.post_status = 'wc-on-hold' OR wp_ot6q6i_posts.post_status = 'wc-completed' OR wp_ot6q6i_posts.post_status = 'wc-cancelled' OR wp_ot6q6i_posts.post_status = 'wc-refunded' OR wp_ot6q6i_posts.post_status = 'wc-failed'
)
) AND EXISTS(
SELECT
t2.PROD_ID
FROM
(
SELECT
wp_ot6q6i_woocommerce_order_itemmeta.meta_value AS PROD_ID
FROM
wp_ot6q6i_woocommerce_order_items
LEFT JOIN
wp_ot6q6i_woocommerce_order_itemmeta
ON
wp_ot6q6i_woocommerce_order_itemmeta.order_item_id = wp_ot6q6i_woocommerce_order_items.order_item_id
WHERE
wp_ot6q6i_woocommerce_order_items.order_item_type = 'line_item' AND wp_ot6q6i_woocommerce_order_itemmeta.meta_key = '_product_id' AND wp_ot6q6i_posts.ID = wp_ot6q6i_woocommerce_order_items.order_id
) t1
INNER JOIN
(
SELECT DISTINCT
wposts.ID AS PROD_ID
FROM
wp_ot6q6i_posts wposts
LEFT JOIN
wp_ot6q6i_postmeta wpostmeta
ON
wposts.ID = wpostmeta.post_id
LEFT JOIN
wp_ot6q6i_term_relationships
ON
(
wposts.ID = wp_ot6q6i_term_relationships.object_id
)
LEFT JOIN
wp_ot6q6i_term_taxonomy
ON
(
wp_ot6q6i_term_relationships.term_taxonomy_id = wp_ot6q6i_term_taxonomy.term_taxonomy_id
)
WHERE
wp_ot6q6i_term_taxonomy.taxonomy = 'product_cat' AND wp_ot6q6i_term_taxonomy.term_id IN(
SELECT
term_id
FROM
`wp_ot6q6i_terms`
WHERE
slug = 'preorder'
)
ORDER BY
wpostmeta.meta_value
) t2
ON
t1.PROD_ID = t2.PROD_ID
)
ORDER BY
wp_ot6q6i_posts.post_date
DESC
LIMIT 0, 20
And the error I'm getting is:
1054 - Unknown column 'wp_ot6q6i_posts.ID' in 'where clause'
Thanks all for your help. I ended up going in a different direction to solve this problem, one I'm more comfortable with as a dev...I'm pulling the fixed list of items from the last join and building a query in code that has a series of more simple queries in the where clause, thereby avoiding the whole Exists approach.
Thanks again for your help.

Select by multiple values in left join

Working with following structure, how can I select a subset of requests respecting multiple conditions in this 1:n relation?
# Table 1: Request
uid
name
# Table 2: Additional Information
uid
type
value
request
Note for table 2: type can be anything, i.e. 'product_name' or 'rating'.
If I'd just want to select Requests by a given product_name I can do this:
SELECT * FROM request as r
LEFT JOIN additional_information as i
ON r.uid = i.request
WHERE i.type = 'product' AND i.value = 'Product Name'
I'm stuck at what my statement must look like if I want to select Requests by a given product_name AND rating. I have tried to simply add another join but this gave me all requests that related to a given product_name as well as all requests related to a given rating. I need the statement to respect both conditions.
This, as mentioned, does not work for me.
SELECT * FROM request as r
LEFT JOIN additional_information as i
ON r.uid = i.request
LEFT JOIN additional_information as a
ON r.uid = a.request
WHERE i.type = 'product' AND i.value = 'Product Name'
OR a.type = 'rating' AND a.value = 1
Appreciate the help!
Move those conditions from WHERE to JOIN ON condition like
SELECT * FROM request as r
LEFT JOIN additional_information as i
ON r.uid = i.request
AND i.type = 'product' AND i.value = 'Product Name'
LEFT JOIN additional_information as a
ON r.uid = a.request
AND a.type = 'rating' AND a.value = 1;
And Yes absolutely, considering the valuable comment (which missed) from Strwabery, instead of doing a select * or select r.* you might actually want to specify the column names you want to fetch which is better than * performance wise since you are not getting unnecessary data using projection; unless you really want to fetch everything.
It might be slow from the other offering since it is joining to your additional data TWICE, once for product, again on rating. This should probably be changed to a single left-join otherwise you could get a Cartesian result bloating your answer.
SELECT *
FROM
request as r
LEFT JOIN additional_information as i
ON r.uid = i.request
AND ( ( i.type = 'product' AND i.value = 'Product Name' )
OR ( i.type = 'rating' AND i.value = 1 );

How to get Wordpress post with title, content and featured image using mysql query

Hi I know this question may seems familiar but please read the full question.
I want to get Wordpress post title,featured image,content using a mysql query.
I tried many queries but I'm getting errors.
there is no error and MySQL query returns empty. I am using Wordpress version 4.5.2.
I found this query but it is giving me an empty result.
SELECT p1.*, wm2.meta_value
FROM wp_posts p1
LEFT JOIN wp_postmeta wm1 ON (
wm1.post_id = p1.id
AND wm1.meta_value IS NOT NULL
AND wm1.meta_key = '_thumbnail_id'
)
LEFT JOIN
wp_postmeta wm2
ON (
wm1.meta_value = wm2.post_id
AND wm2.meta_key = '_wp_attached_file'
AND wm2.meta_value IS NOT NULL
)LEFT JOIN
wp_term_relationships wtr
ON
(
object_id=p1.id
)
WHERE
p1.post_status='publish'
AND p1.post_type='post'
AND 'term_taxonomy_id'='454'
ORDER BY p1.post_date DESC
LIMIT 0,10
How can I improve this query to return results?
You have an error in SQL's WHERE clause:
AND 'term_taxonomy_id'='454'
The string 'term_taxonomy_id' will never be equal to the string '454'.
First, to check, remove this condition entirely from your query. If you get results back and you still want to filter by this taxonomy_id then remove the single quote marks around the field name:
SELECT p1.*,
wm2.meta_value
FROM wp_posts p1
LEFT JOIN wp_postmeta wm1 ON (
wm1.post_id = p1.id
AND wm1.meta_value IS NOT NULL
AND wm1.meta_key = '_thumbnail_id'
)
LEFT JOIN wp_postmeta wm2 ON (
wm1.meta_value = wm2.post_id
AND wm2.meta_key = '_wp_attached_file'
AND wm2.meta_value IS NOT NULL
)
LEFT JOIN wp_term_relationships wtr ON (object_id = p1.id)
WHERE p1.post_status = 'publish'
AND p1.post_type = 'post'
AND term_taxonomy_id = '454'
ORDER BY p1.post_date DESC LIMIT 0,10
In MySQL you can use backticks around field names, but single quotes are used around string literals. If you mix those up, you'll be in trouble.
If you are still not getting results consider removing the p1.post_status and p1.post_type restrictions to see if you get results back and tweak accordingly.

Problems with simple MySQL join

I am working with Expression Engine and the query module which allows you to use MySQL to get results. I have a set of data which I'm trying to associate with a user. My query is currently as follows:
SELECT COUNT(*)
FROM exp_channel_grid_field_11
INNER JOIN exp_member_data
WHERE `col_id_12` = 'Race' && `member_id` = '1'
So, I'm not too clued up when it comes to joins, but I am just looking for the count. Thanks.
Not sure what you're after - you don't necessarily need an 'ON' to do a JOIN but perhaps you do need to define the tables. I don't know which columns belong to which tables (and neither does mysql, perhaps that's the problem)
Assuming that 'member_id' is in exp_member_data and 'col_id_12' is in exp_channel_grid_field_11, you probably need to do something like this:
SELECT COUNT(*)
FROM exp_channel_grid_field_11
INNER JOIN exp_member_data
WHERE `exp_channel_grid_field_11.col_id_12` = 'Race'
&& `exp_member_data.member_id` = '1'
and you can "pretty it up" with "table aliases" such as like this:
SELECT COUNT(*)
FROM exp_channel_grid_field_11 e11
INNER JOIN exp_member_data ed
WHERE `e11.col_id_12` = 'Race'
AND `ed.member_id` = '1'
Or, maybe there should be an 'ON' member_id?
SELECT COUNT(*)
FROM exp_channel_grid_field_11 e11
INNER JOIN exp_member_data ed
ON e11.member_id = ed.member_id
WHERE `e11.col_id_12` = 'Race'
AND `ed.member_id` = '1'
In stead of WHERE col_id_12 = 'Race', use: on col_id_12 = 'Race'
SELECT COUNT(*)
FROM exp_channel_grid_field_11
INNER JOIN exp_member_data ON `col_id_12` = 'Race'
WHERE `member_id` = '1'

Combine many joins into one join?

There are two tables - incoming tours(id,name) and incoming_tours_cities(id_parrent, id_city) where id_parrent is id from first table.
Here is the query i wrote
SELECT t.cities
FROM `incoming_tours` t
JOIN `incoming_tours_cities` tc0 ON tc0.id_parrent = t.id
AND tc0.id_city = '1'
JOIN `incoming_tours_cities` tc1 ON tc1.id_parrent = t.id
AND tc1.id_city = '6'
And now, what is the question...
Why i can't write both conditions in single join?(i.e. i can, but it returns empty result.)
as i understand joins, when i wrote
JOIN incoming_tours_cities tc ON tc.id_parrent = t.id
it must return the list of rows where the condition is true. isn't it?
So why i can't write
SELECT t.cities
FROM `incoming_tours` t
JOIN `incoming_tours_cities` tc ON tc.id_parrent = t.id
AND tc.id_city = '1'
AND tc.id_city = '6'
And maybe there is more efficient method to rich same effect(because in my structure the count of conditions can be very big)
Thanks much
the value of tc.id_city cannot be both '1' and '6' simultaneously. I think you want an OR rather than an AND:
SELECT t.cities
FROM `incoming_tours` t
JOIN `incoming_tours_cities` tc ON tc.id_parrent = t.id
AND (tc.id_city = '1'
OR tc.id_city = '6')
Think of it this way. If you ask for rows from incoming_tour_cities for which the id_city value is '1' and is also at the same time '6', how many rows will you match?
What you really want is:
SELECT t.cities
FROM `incoming_tours` t
JOIN `incoming_tours_cities` tc ON tc.id_parrent = t.id
WHERE (tc.id_city = '1' OR tc.id_city = '6')
or, more compactly:
SELECT t.cities
FROM `incoming_tours` t
JOIN `incoming_tours_cities` tc ON tc.id_parrent = t.id
WHERE tc.id_city IN ('1', '6')
An alternative answer based on the user's clarification that the first query is the one he wants to duplicate.
Here is the only "short cut" way I know of doing this, where "short cut" means not performing two independent tests (using JOINs or EXISTs clauses):
SELECT t.cities
FROM `incoming_tours` t
JOIN `incoming_tours_cities` tc ON tc.id_parrent = t.id
WHERE tc.id_city IN ('1', '6')
GROUP BY t.cities HAVING COUNT(DISTINCT tc.id_city) > 2