MySQL get rows, but for any matching get the latest version - activerecord

I'm developing a CMS, and implementing versioning by adding a new entry to the database with the current timestamp.
My table is set up as follows:
id | page | section | timestamp | content
"Page" is the page being accessed, which is either the path to the page ($page_name below), or '/' (to indicate 'global' fields).
"Section" is the section of the page being edited.
I want to be able to select all rows for a given page, but each section should only be selected once, the one with the latest timestamp being selected.
I've tried using the following CodeIgniter Active Record code:
$this->db->select('DISTINCT(section), content');
$this->db->where_in('page', array('/', $page_name));
$this->db->order_by('timestamp', 'desc');
$query = $this->db->get('cms_content');
Which is producing the following SQL:
SELECT DISTINCT(section), `content`
FROM (`cms_content`)
WHERE `page` IN ('/', 'index.html')
AND `enabled` = 1
ORDER BY `timestamp` desc
Which is returning both test rows (rows have all same fields except id, timestamp and content).
Any ideas as to where I'm going wrong?
Thanks!

Your mistake is thinking that DISTINCT applies only to section - an easy mistake to make as the parentheses are misleading here. In fact the DISTINCT applies to the entire row whether or not you have parentheses. It is therefore best to omit the parentheses to avoid confusion.
Your problem is a classic 'max per group' problem. There are many, many ways to write this query and it is probably one of the most popular SQL questions on this site so you can search Stack Overflow to find ways to solve it. One way to get you started is to only select rows which hold the maximum timestamp for that section:
SELECT section, content
FROM cms_content T1
WHERE page IN ('/', 'index.html')
AND enabled = 1
AND timestamp = (
SELECT MAX(timestamp)
FROM cms_content T2
WHERE page IN ('/', 'index.html')
AND enabled = 1
AND T1.section = T2.section
)
I'm sorry but I do not know how to convert this SQL code into CodeIgniter Active Record. If another user more familiar with Active Record wishes to use this as a starting point for their own answer, they are welcome.

DISTINCT is for all columns selected, and because "content" differs you will get two different rows.
You only want to order by timestamp and limit 1 because you always want the latest.
But may I suggest that you keep a cross reference to the "active" page? That way, you are able to revert to a previous revision without dumping the new ones.
Meaning:
page
----
id
info
active_page_id
page_revisions
--------------
id
page_id
content
timestamp
...
Meaning, you have one-to-many between page <-> page_revisions, aswell as a one-to-one between page and page_revisions to keep track of the "current" revision. With this approach you are able to just join in the active revision.

This will do the job in Codeigniter, without temporary tables:
$this->db->query( "SELECT *
FROM cms_content AS c1
LEFT JOIN cms_content AS c2
ON c1.page=c2.page
AND c1.section=c2.section
AND c1.timestamp < c2.timestamp
WHERE c2.timestamp IS NULL AND page=?", $page );

Related

In oracle apex how to navigate to different pages from link column depending on another column data

I have a table with multiple columns in that one column have data like text field in that data is either A or B and another column is of link type link is getting fetched by id column, Now I have a situation by comparing the data in column1 if it's 'A' I want to navigate to page 3 and If it's 'B' I want to navigate to page 4 by click of link column. How to achieve this?
It would probably be easier for us if you actually shared table and its contents instead of describing it; moreover, as you wrote it as a single sentence with no punctuation, it is difficult to understand what you want to say.
The way I understood it, table is used as a source for some kind of a report (interactive or classic?). One of its (reports) columns is used as a link to another page. As link depends on column's value, I suggest you use a case expression and compose link to target page.
I don't know how you are creating the link now, but - if you already don't use it - have a look at GET_URL function which does most of the dirty job for you. In its simplest appearance, you'd just
select id,
apex_page_get_url(p_page => case when column1 = 'A' then 1
when column2 = 'B' then 2
end) as link
from ...
You need to create Dynamic action on Button.
Button -> True -> Action := Execute server-side-code
Settings -> language := PLSQL
FOR PLSQL QUERY
3)Items to Submit = P7_NEW,P7_NEW_1
4) Items to Return = P31_URL
This will create URL and Trigger the URL to next page

SSRS Tablix Cell Calculation based on RowGroup Value

I have looked through several of the posts on SSRS tablix expressions and I can't find the answer to my particular issue.
I have a dashboard I am creating that contains summary data for various managers. They are entering monthly summary data into a single table structured like this:
Create TABLE OperationMetrics
AS
Date date
Plant char(10)
Sales float
ReturnedProduct float
The data could use some grouping so I created a table for referencing which report group these metrics go into looks like this:
Create Table OperationsReport
as
ReportType varchar(50)
MetricType varchar(50)
In this table, 'Sales' and 'ReturnedProduct' are the Metric column, while 'ExecSummary' or 'Quality' are ReportType entries. To do the join, I decided to UNPIVOT the OperationMetrics table...
Select Date, Plant, Metric, MetricType
From (Select Date, Plant, Sales, ReturnedProduct From OperationMetrics)
UNPVIOT (Metric for MetricType in (Sales, ReturnedProduct) UnPvt
and join it to the OperationsReport table so I have grouped metrics.
Select Date, Plant, Metric, Rpt.MetricReport, MetricType
FROM OpMetrics_Unpivoted OpEx
INNER JOIN OperationsReport Rpt on OpEx.MetricType = Rpt.MetricType
(I understand that elements of this is not ideal but sometimes we are not in control of our destiny.)
This does not include the whole of the tables but you get the gist. So, they have a form they fill in the OperationMetrics table. I chose SSRS to display the output.
I created a tablix with the following configuration (I can't post images due to my rep...)
Date is the only column group, grouped on 'MMM-yy'
Parent Row Group is the ReportType
Child Row Group is the MetricType
Now, my problem is that some of the metrics are calculations of other metrics. For instance, 'Returned Product (% of Sales)' is not entered by the manager because it is assumed we can simply calculate that. It would be ReturnedProduct divided by Sales.
I attempted to calculate this by using a lookup function, as below:
Switch(Fields!FriendlyName.Value="Sales",SUM(Fields!Metric.Value),
Fields!FriendlyName.Value="ReturnedProduct",SUM(Fields!Metric.Value),
Fields!FriendlyName.Value="ReturnedProductPercent",Lookup("ReturnedProduct",
Fields!FriendlyName.Value,Fields!Metric.Value,"MetricDataSet")/
Lookup("Sales",Fields!FriendlyName.Value,Fields!Metric.Value,
"MetricDataSet"))
This works great! For the first month... but since Lookup looks for the first match, it just posts the same value for the rest of the months after.
I attempted to use this but it got me back to where I was at the beginning since the dataset does not have the value.
Any help with this would be well received. I would like to keep the rowgroup hierarchy.
It sounds like the LookUp is working for you but you just need to include the date to find the right month. LookUp will return the first match which is why it's only working on the first month.
What you can try is concatenating the Metric Name and Date fields in the LookUp.
Lookup("Sales" & CSTR(Fields!DATE.Value), Fields!FriendlyName.Value & CSTR(Fields!DATE.Value), Fields!Metric.Value, "MetricDataSet")
Let me know if I misunderstood the issue.

magento url rewrite useless?

Two points I want to mention.
First Point.
I noticed a strange behavior, most probably a bug.
I configured a new clean instance of Magento (no other module, so from scratch) and an empty database.
I created 3 categories below the root one.
And 3 products, one in each category.
Something like:
Cat 1
+ Prod 1
Cat 2
+ Prod 2
Cat 3
+ Prod 3
If I change the order of the category so "Cat 3" is before "Cat 2" like this:
Cat 1
+ Prod 1
Cat 3
+ Prod 3
Cat 2
+ Prod 2
I just need to drag and drop "Cat 3" above "cat 2" from the category management screen.
So the "order" number of cat2 and cat3 are actually exchanged.
BUT the url index process reindexes ALL products of ALL categories (URL REWRITE index)!
I analyzed the SQL log, and it actually does an INSERT with every single product in the database.
I see insert in core_url_rewrite for "Prod 1", "Prod 2" and "Prod 3".
This is a bug, because "Cat 3" keeps the same parent category, so:
1) there is no need to rewrite products within "Cat 3" (the product name didn 't change, the category name didn't change!!)
2) there is no need to rewrite products linked to other categories
Actually, by doing a select, I can see that the rows of the core_url_rewrite table are the same (for sure as no name changed! and no association between products and any categories above the products changed!)
Here is one SQL query that I see out of the log file wen I move the category:
SQL: INSERT INTO `core_url_rewrite` (`store_id`,`category_id`,`product_id`,`id_path`,`request_path`,`target_path`,`is_system`) VALUES (?, ?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE store_id = VALUES(`store_id`), category_id = VALUES(`category_id`), product_id = VALUES(`product_id`), id_path = VALUES(`id_path`), request_path = VALUES(`request_path`), target_path = VALUES(`target_path`), is_system = VALUES(`is_system`)
BIND: array (
0 => '1',
1 => NULL,
2 => '4',
3 => 'product/4',
4 => 'testun.html',
5 => 'catalog/product/view/id/4',
6 => 1,
)
AFF: 0
TIME: 0.0005
Actually, the worse thing is, it does an insert of a row that already exist, so it actually does not insert anything. The insert failed (you can see "AFF: 0" meaning nothing has been inserted)
It is a waste of time to process each product for nothing, and try to insert something that might be already there!!
Second points
I found another bug/strange behavior.
If I have 2 products with the same name (it can happen), then the url key is the same (by default).
BTW url key is also the same by default when you duplicate a product to create a new one.
So The reindex process becomes crazy.
eg, 2 products with the name "camera" will have the url rewrting like this:
camera-1.html
camera-2.html
I'm ok with this.
BUT, if now I reindex everything, it becomes crazy.
it will change the url rewriting of those products (even if I didn't change anything related to those products).
it will update the 2 products like this:
UPDATE camera-1.html => camera-3.html
UPDATE camera-2.html => camera-4.html
and insert redirection if the setting is enabled (so previous links are not lost), somethign like
INSERT camera-1.html , camera-3.html ,RP
INSERT camera-2.html , camera-4.html , RP
RP options is about permanent redirect.
So 2 useless updates and 2 useless Insert for nothing.
If I reindex again, I wait the end, and reindex immediately, then Magento does 4 updates, 4 inserts etc.
Why?? No change at all with any data between the reindex :-)
If you have 5 000 products with the same name (like I have), then it's 10 000 updates and 10 000 (real) insert for nothing...
Size of core_url_rewrite increase again and again on a daily basis. Suration is extremely high
Note: I have a good reason to have 5 000 products with exactly the same name :-)
Whatever my reason this looks strange.
Have you already checked this?
Quite easy to check with a fresh installation of magento and log files enabled.
Last thing is, why do we need the core_url_rewrite table?
This is one of the main cause of performance issue with magento!
4 lines of php code+htaccess url rewrite would do exactly the same job, no need of a DB Table for this (except for custom url rewrite or CMS page).
one method to generate dynamically the url of a product (based on name and category if needed) and one to generate the url of a category.
then htaccess to redirect.
you just need a keyword in the url to know whether it is a link to a product or a category, and its ID.
something like:
my-cat/camera-112-p.html
htacces URL rewrite detects it's a link to a product (because of -p.htm), it gets the product id out of the url (112) and redirect the user accordingly.
having the product ID might looks ugly or an issue with SEO, but I don't think so (not as bad as you can read).
And it has to be balanced with the big benefit:
1) no huge table anymore
2) no need to reindex this table (this takes hours, like 8 hours, with a lot of magento website). This process can cause a lot of timeout issue, locking etc.
at least this should be possible through an option (or a module).
Note also that you don't even need to care about permanent redirection, since the content (text) within the link does not matter! Just the ID matters.
Does it exist? if yes I will definetely buy it to say "bye-bye" to this complex messy mechanism (with bugs)
any feedback will be hight appreciated.
(especially if you find any rational in the way magento behaves, taken into account the poor performance linked to use/manage this table, so the rationnal has to be highly appreciated :-) )
thanks
Rod
Point one and two seem to have been addressed see the notes for EE 1.13.0.2 (released today, CE 1.7 coming soon): http://www.magentocommerce.com/knowledge-base/entry/ee113-later-release-notes#prod-url-unique
But, it's worth addressing some of your points.
Why do/did URL rewrites work this way? Because that's the way they worked - it's just how they were created/evolved, including the racing rewrite bug you noticed when two products have the same url_key.
Based on a lot of benchmarking and experience, I can state that the core_url_rewrite table is not "the main cause of poor performance in Magento". The reindex process can suck though, no doubt.
The URL rewrite table is necessary for custom rewrites in general. Suggesting that manipulation of server config files (e.g. Apache .htaccess) to add rewrites fails to consider that Magento is an application which can be modified and extended without direct developer knowledge (e.g. by store owner).
The suggestion to use a pretty-urls mod_rewrite pattern is not tenable for any shop concerned with SEO, and I assure you that the URL path is quite important to ranking/relevance.

Passing more than 3 items in a reports column link

I have a report that is listing students and I want a column to edit a student. I've done so by following this answer:
How do you add an edit button to each row in a report in Oracle APEX?
However, I can only seem to pass 3 items and there's no option to add more. I took a screenshot to explain more:
I need to pass 8 values, how can I do that?
Thanks!
Normally, for this you would only pass the Primary Key columns (here looks like #RECORD_NUMBER# only). The page that you send the person to would then load the form based on the primary key lookup only. If multiple users were using this application, you would want the edit form to always retrieve the current values of the database, not what happened to be on the screen when a particular person ran a certain report.
Change the Target type to URL.
Apex will format what to already have into a URL text field which magically appears between Tem3 and Page Checksum.
All you need to do is to add your new items and values in the appropriate places in the URL.
I found a workaround, at least it was useful to my scenario.
I have an IR page, query returns 4 columns, lets say: ID, DESCRIPTION, SOME_NUMBER,SOME_NUMBER2.
ID NUMBER(9), DESCRIPTION VARCHAR2(30), SOME_NUMBER NUMBER(1), SOME_NUMBER2 NUMBER(3).
What I did was, to setup items this way:
P11_ITEM1-->#ID#
P11_ITEM2-->#DESCRIPTION#
P11_ITEM3-->#SOME_NUMBER##SOME_NUMBER2#
Previous data have been sent to page 11.
In page 11, all items are display only items.
And P11_ITEM3 actually received two concatenated values.
For example, the calling page has columns SOME_NUMER=4 and SOME_NUMBER2=150
so, in pag1 11, P11_ITEM3 shows 4150
In page 11 I created a Before Footer process (pl/sql expression)
to set up new items, for example P11_N1 as source SUBSTR(P11_ITEM3,1,1)
and item P11_N2 as source SUBSTR(P11_ITEM3,2,3)
So, I had those items with corresponding values from the calling IR page.
The reason I did not pass the primary key only for new lookup access, is because i do not want to stress database performing new queries since all data are already loaded into page items. I've been an oracle DBA for twenty years and I know there is no need to re execute queries if you already have the information somewhere else.
These workarounds are not very useful for a product that bills itself as a RAD tool.
Just include a single quoted word in the select statement (Select col1, 'Randomword', col2 from table 1;)
Then define that column as a link and bingo! More items than 3 to select.

Custom Start Number for Order Numbers in Magento 1.5

How do I customise the starting number for orders, invoices etc in Magento 1.5?
From magento's forum:
by LindyKyaw (Magento Team Member), changing start number (through sql query):
There is a table in the database which stored increment id of order.
It is called “eav_entity_store” table.
You can check which entity type id belongs to which entity by looking at
eav_entity_type table.
You can run following query to update last increment id for the order.
update eav_entity_store
inner join eav_entity_type on eav_entity_type.entity_type_id = eav_entity_store.entity_type_id
set eav_entity_store.increment_last_id=3001
where eav_entity_type.entity_type_code='order';
by FOOMAN (active contributor), changing start number (through db management tool) and removing "0"s at the beginning:
With a tool like phpmyadmin look at your database. In the table
eav_entity_type you will find all entity types listed. The one of interest to
change where the order number starts is order sales/order. Remember the
entity_type_id (in my install it is 11). To remove the leading zeros
(padding) set increment_pad_length to 1.
Next go to the table eav_entity_store. Look up the entity_type_id. Now you
can change the value of increment_prefix and increment_last_id. If you wanted to
have your next orderId to be 15000 set increment_last_id to 14999 and
increment_prefix to 0.
Additionally you need to make a copy of this file
/app/code/core/Mage/Eav/Model/Entity/Increment/Abstract.php
to
/app/code/local/Mage/Eav/Model/Entity/Increment/Abstract.php
public function getPadLength()
{
$padLength = $this->getData('pad_length');
if (empty($padLength)) {
$padLength = 0;
}
return $padLength;
}
...
public function format($id)
{
$result= str_pad((string)$id, $this->getPadLength(), $this->getPadChar(), STR_PAD_LEFT);
return $result;
} Hope That Helps
Actually with the newer versions (and probably in 1.5 as well), there is an easier way to change it. In PHPMyAdmin, or your mysql client, go to the eav_entity_type table. Locate the table in the entity_type_code column (probably order), and set the increment_pad_length to be whatever you would like, as well as the increment_pad_char.
Then you don't have to rewrite core code - a win-win.
JMax
Magento Order No
It's simple....
go to phpmyadmin
select your datbase and then select the table "eav_entity_store"
in this table, change the increment_last_id (for example, I have set 3456767 in my table)
after that I create a new order. Now my orders start from the number 346768
There is actually a good extension for accomplish this task.
It allows you to customize the order ID in a lot of different way:
for example you can use a combination of:
number like year,month,,day,hr,sec,
use a custom counter (you can decide the starting number )
a combination of all above methods
add some custom string in any position of the order ID
This is the ext. on Magento connect:
http://www.magentocommerce.com/magento-connect/custom-order-id-8210.html
I personally tried it and it very good ( works fine with all my payment methods and I had no issue at all )

Resources