MySQL Show Result Twice Given Different Condition - mysql

I have the following code which I'm using to get prices from a Magento database:
SELECT
`e`.`sku`,
`price_index`.`price` AS `RRP`,
`price_index`.`final_price` AS `Dealer Price`
FROM
`catalog_product_entity` AS `e`
INNER JOIN
`catalog_product_index_price` AS `price_index` ON price_index.entity_id = e.entity_id AND
price_index.website_id = '1' AND price_index.customer_group_id = 7
This works fine, however I need to get an additional price from "final_price" but with customer group 8 instead of 7 for example.
The results from my current script display:
SKU, RRP, Dealer Price
The Results I would like:
SKU, RRP, Dealer Price, Trader Price
Thanks

You just need left joins instead of inner joins. Note in the tested example below that I'm renaming the alias of price_index to price_index2 in the second join on the same table.
SELECT
`e`.`sku`,
`price_index`.`price` AS `RRP`,
`price_index`.`final_price` AS `Dealer Price`,
`price_index2`.`final_price` AS `Trader Price`
FROM
`catalog_product_entity` AS `e`
LEFT JOIN
`catalog_product_index_price` AS `price_index` ON price_index.entity_id = e.entity_id AND
price_index.website_id = '1' AND price_index.customer_group_id = 7
LEFT JOIN
`catalog_product_index_price` AS `price_index2` ON price_index2.entity_id = e.entity_id AND
price_index2.website_id = '1' AND price_index2.customer_group_id = 8

Related

How to convert a NOT IN query into a JOIN query

I have this following query that needs to be optimized
Select
1 As status,
e.entity_id,
e.attribute_set_id,
e.type_id,
e.created_at,
e.updated_at,
e.sku,
e.name,
e.short_description,
e.image,
e.small_image,
e.thumbnail,
e.url_key,
e.free,
e.number_of_downloads,
e.sentence1,
e.url_path
From
catalog_product_flat_1 As e
Inner Join catalog_category_product_index_store1 As cat_index
On cat_index.product_id = e.entity_id And
cat_index.store_id = 1 And
cat_index.visibility In (3, 2, 4) And
cat_index.category_id = '2'
Where
e.entity_id Not In (13863, 14096, 13856, 13924, 15875, 15869, 13788, 15977, 15873, 17141, 22214, 16900, 14485,
15628, 15656, 14220, 14259, 14284, 13875, 13216, 14168, 13892, 16540, 19389, 17286, 16591, 30178, 31517, 31734,
31621, 2487, 2486, 2485, 2484, 2483, 2482, 2481, 2480, 2479, 2478, 2477, 2475, 2474, 2473, 13402, 13427, 13694,
13774, 13804, 13837, 13849, 13864, 30299, 30300) And
e.free = 1
Order By
e.number_of_downloads Desc;
Here The ids passed in NOT IN() are the "product_id" column values from a table named "mcsdownloads"
So my goal here is to replace NOT IN with a JOIN operation on table "mcsdownloads".
please help !
You are looking for LEFT JOIN ... WHERE ... IS NULL:
SELECT ...
From catalog_product_flat_1 As e
Inner Join catalog_category_product_index_store1 As cat_index
ON cat_index.product_id = e.entity_id
LEFT JOIN mcsdownloads AS m ON m.entity_id = e.entity_id
WHERE cat_index.store_id = 1
And cat_index.visibility In (3, 2, 4)
And cat_index.category_id = '2'
AND e.free = 1
AND m.entity_id IS NULL
(Note: I moved the filtering criteria from ON to WHERE. ON is used for saying how tables relate; WHERE is for filtering.)
Indexes needed:
cat_index: INDEX(store_id, category_id, visibility, product_id)
e: INDEX(free, number_of_downloads)
m: INDEX(entity_id)
I don't think there is a way to perform a join instead of not in, but you can arrange your code in the following way so that it works correctly without manually writing down all the product_id from the mcsdownloads table
SELECT
1 AS status, e.entity_id, e.attribute_set_id,
e.type_id, e.created_at, e.updated_at, e.sku,
e.name, e.short_description, e.image, e.small_image,
e.thumbnail, e.url_key, e.free, e.number_of_downloads,
e.sentence1, e.url_path
FROM catalog_product_flat_1 AS e
INNER JOIN catalog_category_product_index_store1 AS cat_index ON cat_index.product_id=e.entity_id
AND cat_index.store_id=1
AND cat_index.visibility IN (3,2,4)
AND cat_index.category_id='2'
WHERE (e.entity_id NOT IN (SELECT product_id FROM mcsdownloads))
AND (e.free = 1)
ORDER BY e.number_of_downloads DESC;
This is the significant part that I changed
e.entity_id NOT IN (SELECT product_id FROM mcsdownloads)

MySQL - #1054 - Unknown column 'childs' in 'on clause'

I'm very new in comlex SQL queries. So, I'm trying to debug SQL statement generated by Magento:
SELECT `e`.*,
`cat_index`.`position` AS
`cat_index_position`,
price_index.price AS
`indexed_price`,
`price_index`.`price`,
`price_index`.`final_price`,
IF(`price_index`.`tier_price`, Least(`price_index`.`min_price`,
`price_index`.`tier_price`),
`price_index`.`min_price`) AS
`minimal_price`,
`price_index`.`min_price`,
`price_index`.`max_price`,
`price_index`.`tier_price`,
GROUP_CONCAT(CONVERT(catalog_product_relation.child_id, CHAR(8))) AS
`children`,
`sfoi`.`price` AS
`confprice`
FROM `catalog_product_entity` AS `e`
INNER JOIN `catalog_category_product_index` AS `cat_index`
ON cat_index.product_id = e.entity_id
AND cat_index.store_id = 1
AND cat_index.visibility IN( 2, 4 )
AND cat_index.category_id = '3'
INNER JOIN `catalog_product_index_price` AS `price_index`
ON price_index.entity_id = e.entity_id
AND price_index.website_id = '1'
AND price_index.customer_group_id = 0
INNER JOIN `catalog_product_index_eav` AS `attributeA`
ON attributeA.entity_id = e.entity_id
AND attributeA.attribute_id = '184'
AND attributeA.store_id = '1'
AND attributeA.value IN ( 50 )
INNER JOIN `catalog_product_index_eav` AS `attributeB`
ON attributeB.entity_id = e.entity_id
AND attributeB.attribute_id = '185'
AND attributeB.store_id = '1'
AND attributeB.value IN ( 95 )
LEFT JOIN `catalog_product_relation`
ON e.entity_id = catalog_product_relation.parent_id
LEFT JOIN `catalog_product_flat_1` AS `sfoi`
ON sfoi.entity_id = `children`
GROUP BY `e`.`entity_id`
ORDER BY `confprice` DESC
LIMIT 9
Everything work fine until:
LEFT JOIN `catalog_product_flat_1` AS `sfoi`
ON sfoi.entity_id = `children`
I get following error:
#1054 - Unknown column 'children' in 'on clause'
I've seen smilar posts, but I can't seem to figure it out by myself. Please, help me.
EDIT:
PHP code that generates this query:
$this->_collection->getSelect()->
joinLeft(
'catalog_product_relation',
'e.entity_id = catalog_product_relation.parent_id',
'GROUP_CONCAT(CONVERT(catalog_product_relation.child_id, CHAR(8))) as children'
);
$this->_collection->getSelect()->joinLeft('catalog_product_flat_1 AS sfoi',
'sfoi.entity_id = children',
'sfoi.price AS confprice'
)->order('confprice desc');
Actually, I'm trying to join two tables (catalog_product_relation and catalog_product_flat_1). But I can't get access to the "children" column after joining first table.
Add the corresponding column to children table in the ON condition.
ON sfoi.entity_id = catalog_product_relation.child_id

Rows results to columns in MySQL Query (prestashop)

I'm trying to create a MySQL query that will list the products attributes on Prestashop together in a single row (I don't want to depend on paid modules).
The current query is:
SELECT
p.id_product AS 'idProduto',
pac.id_attribute,
al.name 'Nome_SKU',
pa.id_product_attribute as 'idSKU',
pl.name AS 'Nome',
pl.description_short AS 'Descricao Curta',
pl.description AS 'Descricao',
pl.meta_title AS 'Meta-Title',
pl.meta_keywords AS 'Meta-keyword',
pl.meta_description AS 'meta-description',
pl.link_rewrite AS 'URL rewrite',
pl.available_now AS 'texto_estoque',
pl.available_later AS 'texto_indisponivel',
pa.quantity as 'Quantidade',
p.price 'Preco',
pa.minimal_quantity 'Quantidade Minima',
p.active AS 'Ativo (0/1)'
FROM
ps_product p
INNER JOIN
ps_product_lang pl ON p.id_product = pl.id_product
INNER JOIN
ps_product_attribute pa ON pl.id_product = pa.id_product
INNER JOIN
ps_product_attribute_combination pac ON pa.id_product_attribute = pac.id_product_attribute
INNER JOIN
ps_attribute_lang al ON al.id_attribute = pac.id_attribute
where pl.id_lang = 6
AND p.id_product = 101
group by pa.id_product_attribute,al.name
And it's results are like this (i.e. id_product 101):
What I need is the results to "group" in a same row by their idSKU to show the values (Nome_SKU) each in one column, beeing like this (i.e. idSKU 647):

SQL JOIN Query - linking four tables

I have the SQL to display ALL the activities and relative Admin permissions (if any) for that activity.
Current SQL Code:
SELECT `activities`.*, `admins`.`admin_role_id`
FROM (`activities`)
LEFT JOIN `admins` ON `admins`.`activity_id`=`activities`.`id` AND admins.member_id=27500
WHERE `activities`.`active` = 1
Returning:
id | name | description | active | admin_role_id (or null)
I then need to detect whether they are an active member within that Activity.
I have the following SQL code:
SELECT DISTINCT `products`.`activity_ID` as joinedID
FROM (`transactions_items`)
JOIN `transactions` ON `transactions`.`id` = `transactions_items`.`id`
JOIN `products` ON `products`.`id` = `transactions_items`.`product_id`
JOIN `activities` ON `activities`.`id` = `products`.`activity_ID`
WHERE `transactions`.`member_id` = 27500
AND `activities`.`active` = 1
Is there any way to merge this into one SQL query. I can't figure out how to use the correct JOIN queries, because of the complexity of the JOINs.
Help please, thanks! :)
Try like this
SELECT `activities`.*, `admins`.`admin_role_id`
FROM (`activities`)
LEFT JOIN `admins` ON `admins`.`activity_id`=`activities`.`id` AND admins.member_id=27500
JOIN (`transactions_items`
JOIN `transactions` ON `transactions`.`id` = `transactions_items`.`id`
JOIN `products` ON `products`.`id` = `transactions_items`.`product_id`)
ON `activities`.`id`=`products`.`activity_ID`
WHERE `transactions`.`member_id` = 27500
AND `activities`.`active` = 1
Seems to me that a query like this would be marginally more comprehensible and (I think) adhere more closely to the spec...
SELECT c.*
, d.admin_role_id
FROM activities c
LEFT
JOIN admins d
ON d.activity_id = c.id
AND d.member_id = 27500
LEFT
JOIN products p
ON p.activity_ID = c.id
LEFT
JOIN transactions_items ti
ON ti.product_id = p.id
LEFT
JOIN transactions t
ON t.id = ti.id
AND t.member_id = 27500
WHERE c.active = 1

MySQL LEFT JOIN do not return all results

I have a query that JOINs some tables to get a list of products including prices, images, country etc.
"product_images" table can have zero or more images but only the default image should be returned. My problem is that in any case the query should return a result for the product even if there is no image in the "product_images" table for that particular product.
The first query example will return a row for each product but just return a random image:
SELECT `cp`.`category_id`, `p`.`id`, `p`.`master`, `p`.`status`, `p`.`sortorder`, `p`.`sku`, `p`.`stock`, `pd`.`name`, `pd`.`short_description`, `pd`.`description`, `pd`.`slug`, `pi`.`image`, `pi`.`path`
FROM `categories_products` AS `cp`
JOIN `products` AS `p` ON (`cp`.`product_id` = `p`.`id`)
JOIN `product_descriptions` AS `pd`
ON (`pd`.`product_id` = `p`.`id`)
LEFT JOIN `product_images` AS `pi`
ON (`pi`.`product_id` = `p`.`id`)
WHERE `cp`.`category_id` = 34
AND `pd`.`locale_id` = 1
AND `p`.`master` = '0'
AND `p`.`status` = '1'
AND `p`.`accessible` = '1'
AND `pd`.`status` = '1'
GROUP BY `p`.`id`
ORDER BY `p`.`sortorder`
Below query will return the default image. But if there is no image in "product_images" the row for that product will not be retrieved. The only difference here is this part: "AND pi.preset = 1"
SELECT `cp`.`category_id`, `p`.`id`, `p`.`master`, `p`.`status`, `p`.`sortorder`, `p`.`sku`, `p`.`stock`, `pd`.`name`, `pd`.`short_description`, `pd`.`description`, `pd`.`slug`, `pi`.`image`, `pi`.`path`
FROM `categories_products` AS `cp`
JOIN `products` AS `p` ON (`cp`.`product_id` = `p`.`id`)
JOIN `product_descriptions` AS `pd`
ON (`pd`.`product_id` = `p`.`id`)
LEFT JOIN `product_images` AS `pi`
ON (`pi`.`product_id` = `p`.`id`)
WHERE `cp`.`category_id` = 34
AND `pi`.`preset` = 1
AND `pd`.`locale_id` = 1
AND `p`.`master` = '0'
AND `p`.`status` = '1'
AND `p`.`accessible` = '1'
AND `pd`.`status` = '1'
GROUP BY `p`.`id`
ORDER BY `p`.`sortorder`
`pi`.`preset` = 1
in WHERE defeats your goal (your LEFT JOIN behaves like INNER ) . Move it to ON:
LEFT JOIN `product_images` AS `pi`
ON (`pi`.`product_id` = `p`.`id` AND `pi`.`preset` = 1)
You may prefer to use a subquery:
LEFT JOIN (SELECT * FROM product_images WHERE preset = 1) AS pi ON ...
Otherwise, the WHERE clause is applied to the entire query, and if there's no image, WHERE pi.preset=1 will reduce your search set to zero rows.