Why does MySQL return duplicate information in the returned JOIN array? - sql

I'm wondering if I'm doing something wrong, or if this is just a quirk in how everything is processed in MySQL. Here's the setup: (I can't seem to find this exact topic anywhere else)
I have two tables order and menu.
menu has an 'id' (for the item), an 'item' and three prices ('prc1' 'prc2' 'prc3') in each row.
menu +----+----------+------+------+------+
|'id'| 'item' |'prc1'|'prc2'|'prc3'|
+----+----------+------+------+------+
| 1 | 'tshirt' | 3.00 | 4.50 | 4.00 |
| 2 | 'socks' | 1.00 | 2.50 | 2.00 |
+----+----------+------+------+------+
order also has an item id to match against the order menu, ('i_id'), and an integer I use for filtering the prices later in php ('prc_id').
order +------+--------+
|'i_id'|'prc_id'|
+--------+------+
| 1 | 1 | # i_id matches id - tshirt and informs to use prc1
| 2 | 3 | # i_id matchis id - socks and uses prc3
+--------+------+
I use JOIN to match the orders up to the items
"SELECT order.prc_id, menu.item, menu.prc1, menu.prc2, menu.prc3
FROM order
LEFT JOIN menu
ON order.i_id = menu.id"
I then get the result back, and initially to make sure everything panned out, I printed the array:
$result = mysql_query($query)
while($row = mysql_fetch_array($result))
{
print_r($row);
}
This is the array I get back (obviously dummy info for the initial tests):
Array
(
[0] => 1 [prc_id] => 1 #the value (1) for 'prc_id' is given twice
[1] => tshirt [item] => tshirt #the value (tshirt) for 'item' is given twice
[2] => 3.00 [prc1] => 3.00 #the value (3.00) for 'prc1' is given twice
[3] => 4.50 [prc2] => 4.50 #etc
[4] => 4.00 [prc3] => 4.00
[0] => 3 [prc_id] => 3
[1] => socks [item] => socks
[2] => 1.00 [prc1] => 1.00
[3] => 2.50 [prc2] => 2.50
[4] => 2.00 [prc3] => 2.00
)
So my question(finally, right? xD)... Why is duplicate data sent back in the array response?
Have I done something wrong? Am I overlooking something?
It's not a huge issue, it doesn't affect my end result, I'd just like to be as precise as possible.
Thank you for your time. :)

If think this is a PHP print_r() problem.
print_r() return a numeric representation and the second the named store row.
EDIT:
Try your query with the Database Query Tool then you will see the original result.

SELECT order.prc_id, menu.item, menu.prc1, menu.prc2, menu.prc3
FROM order
LEFT JOIN menu
ON order.i_id = menu.id
It looks like you are joining based on the item_id in order and id of menu, while you should be doing based on (if I understand correctly) the item_id of menu.
Something like:
SELECT order.prc_id, menu.item, menu.prc1, menu.prc2, menu.prc3
FROM order
LEFT JOIN menu
ON order.i_id = menu.item_id

Related

Prefix or append a string to meta_title, meta_key, meta_description in category page

Category page meta_title, meta_key and meta_description tags come from the table ps_category_lang.
mysql> select * from ps_category_lang limit 1;
+-------------+---------+---------+-------+-------------+--------------+------------+---------------+------------------+
| id_category | id_shop | id_lang | name | description | link_rewrite | meta_title | meta_keywords | meta_description |
+-------------+---------+---------+-------+-------------+--------------+------------+---------------+------------------+
| 1 | 1 | 1 | Raíz | | raiz | | | |
+-------------+---------+---------+-------+-------------+--------------+------------+---------------+------------------+
1 row in set (0.00 sec)
Is it possible to add a prefix (or suffix) to those three values, so it uses the information from the database but it appends or prefixs a certain value?
If so, what shall be needed to be done? I already have a custom module overriding the category page with extended template and controller.
Prestashop 1.7.1
The best way is by overriding the /classes/controller/FrontController.php, specifically the method getTemplateVarPage() in the code:
$page = array(
'title' => '',
'canonical' => $this->getCanonicalURL(),
'meta' => array(
'title' => $meta_tags['meta_title'],
'description' => $meta_tags['meta_description'],
'keywords' => $meta_tags['meta_keywords'],
'robots' => 'index',
),
'page_name' => $page_name,
'body_classes' => $body_classes,
'admin_notifications' => array(),
);
Here you could validate the current page and alterate it as your needs.
for each standard controller in PrestaShop, you have a dedicated function in the Meta class, in your case, the getCategoryMetas() function that you can override and adapt to fit your needs.
You also can use the previous answer to rewrite the metas firstly computed in the Meta::getCategoryMetas() in CategoryController::getTemplateVarPage() function.
Good luck

magento: join product with attribute value

I'm trying to list some of my product from a php script and I need to get some attributes's value. For exemple I'm trying something like this::
Mage::app();
Mage::app()->setCurrentStore(1);
$collection = Mage::getModel('catalog/product')->getCollection()
->addAttributeToSelect('computer_type')
->joinAttribute('computer_type_value', 'eav/entity_attribute_option', "computer_type", null, 'left', 0)
"computer_type" from product collection store an id which is found in option_id field of the eav_attribute_option_value table:
+----------+-----------+----------+--------+
| value_id | option_id | store_id | value |
+----------+-----------+----------+--------+
| 3738 | 14 | 0 | server |
+----------+-----------+----------+--------+
I would like to join this table with my collection's result in order to have the value "server" displayed instead of the id "3738" but the way I'm doing it is not working and despite all my search.
I didn't find how to achieve that in only one query. Is it possible ?
Please use below code for join product attribute:
$mageFilename = 'app/Mage.php';
require_once $mageFilename;
umask(0);
Mage::app('admin');
Mage::register('isSecureArea', 1);
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
$collection = Mage::getModel('catalog/product')
->getCollection()
->addAttributeToSelect('*')
->addAttributeToFilter('computer_type',array('neq'=>0))
->addAttributeToFilter('status', Mage_Catalog_Model_Product_Status::STATUS_ENABLED)
->addAttributeToFilter('visibility', Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH);

Lithium Model find query with <> operator

I'm trying to fetch rows excluding the one which already are in an other table :
| Content | ContentSelected
| –––––––– | ––––––––––––––––––––––––-
| id | content_id | operation_id
| 1 | 1 | 9999
| 2 | 3 | 1000
| 3
=> 2,3
Here how I tried to run this query :
Content::find('all', array(
'joins' => array(new Query(array(
'source' => 'ContentSelected',
'constraints' => array('ContentSelected.operation_id' => 9999),
'conditions' => array(
'Content.id' => array('<>' => 'ContentSelected.content_id')
));
Here the SQL query run by the adapter :
SELECT * FROM "Content" AS "Content"
JOIN "ContentSelected" ON "ContentSelected"."operation_id" = 1
WHERE ("Content"."id" <> 0);
Is there another way to performed a query excluding results, or to force the adapter to write ContentSelected.content_id instead of 0 in the where clause ?
Thanks
You can use Model::connection()->read() to run a native sql in Li3. Check this out http://www.jblotus.com/2011/10/25/executing-raw-mysql-queries-in-lithium/
Content::connection()->read($your_sql);
But before using such a solution. Try to implement your model properly using Model Relationships (http://li3.me/docs/manual/models/relationships.md) so that you don't need to use a native query and let the model does the work for you.

Redis find key based on set value

Im using redis to store tags for certain entities. Examples of the data:
+-------------+--------------------------------+
| key | value |
+-------------+--------------------------------+
| book:1:tags | [python, ruby, rails] |
+-------------+--------------------------------+
| book:2:tags | [fiction, fantasy] |
+-------------+--------------------------------+
| book:3:tags | [fiction, adventure] |
+-------------+--------------------------------+
How do I find all books with a particular tag, ie all books tagged with fiction?
You have to maintain reverse indexes yourself. Along with those keys that you posted, you should create reverse references.
tag:python => [1]
tag:ruby => [1]
tag:rails => [1]
tag:fiction => [2, 3]
tag:fantasy => [2]
tag:adventure => [3]
Then it's trivial to do what you want. But maybe you should consider using another tool for the job. For example, MongoDB can efficiently index and query arrays.

Grouped aggregations with Yii STAT?

I have a Yii STAT Relation that's defined to provide a grouped SUM result, however when I access the relation in my View, the only value is the latest single value rather than each value.
For example, here's my relation:
'total_salaries_by_job' => array(
self::STAT,
'Employee',
'department_id',
'select' => 'job_type_id, SUM(salary)',
'group'=>"job_type_id"
)
This generates the following SQL:
SELECT
department_id AS c
, job_type_id
, SUM(salary) AS s
FROM Employee AS t
WHERE t.department_id = 1
GROUP BY
department_id
, job_type_id
Running that manually, the result set is:
c | job_type_id | s
------+----------------+---------
1 | 1 | 233000
------+----------------+---------
1 | 2 | 25000
------+----------------+---------
1 | 3 | 179000
However, in my view, if I do the following:
<pre>
<?php print_r($department->total_salaries_by_job); ?>
</pre>
The result is simply: 179000, whereas I was expecting it to be an array with 3 elements.
Is returning just 1 value the way STAT relations work or is there something else I need to be doing?
Is it possible to do what I'm attempting?
You can do what you are after, but you can't use a STAT relationship to do it. Rather, use a Normal HAS_MANY relationship and use your same select statement.