Question

Have a table containing form data. Each row contains a section_id and field_id. There are 50 distinct fields for each section. As users update an existing field, a new row is inserted with an updated date_modified. This keeps a rolling archive of changes.

The problem is that I'm getting erratic results when pulling the most recent set of fields to display on a page.

I've narrowed down the problem to a couple of fields, and have recreated a portion of the table in question on SQLFiddle.

Schema:

CREATE TABLE IF NOT EXISTS `cTable` (
  `section_id` int(5) NOT NULL,
  `field_id` int(5) DEFAULT NULL,
  `content` text,
  `user_id` int(11) NOT NULL,
  `date_modified` datetime NOT NULL,
  KEY `section_id` (`section_id`),
  KEY `field_id` (`field_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

This query shows all previously edited rows for field_id 39. There are five rows returned:

SELECT cT.* 
FROM cTable cT 
WHERE 
 cT.section_id = 123 AND
 cT.field_id=39;

Here's what I'm trying to do to pull the most recent row for field_id 39. No rows returned:

SELECT cT.* 
FROM cTable cT 
INNER JOIN (
  SELECT field_id, MAX(date_modified) AS date_modified
  FROM cTable GROUP BY field_id
) AS max USING (field_id, date_modified)
WHERE 
 cT.section_id = 123 AND
 cT.field_id=39;

Record Count: 0; 

If I try the same query on a different field_id, say 54, I get the correct result:

SELECT cT.* 
FROM cTable cT 
INNER JOIN (
  SELECT field_id, MAX(date_modified) AS date_modified
  FROM cTable GROUP BY field_id
) AS max USING (field_id, date_modified)
WHERE 
 cT.section_id = 123 AND
 cT.field_id=54;

Record Count: 1; 

Why would same query work on one field_id, but not the other?

Was it helpful?

Solution

In your subquery from where you are getting maxima you need to GROUP BY section_id,field_id using just GROUP BY field_id is skipping the section id, on which you are applying filter

SELECT cT.* 
FROM cTable cT 
INNER JOIN (
  SELECT section_id,field_id, MAX(date_modified) AS date_modified
  FROM cTable GROUP BY section_id,field_id
) AS max 
ON(max.field_id =cT.field_id 
   AND max.date_modified=cT.date_modified
 AND max.section_id=cT.section_id
  )
WHERE 
cT.section_id = 123 AND
 cT.field_id=39;

See Fiddle Demo

OTHER TIPS

You are looking for the max(date_modified) per field_id. But you should look for the max(date_modified) per field_id where the section_id is 123. Otherwise you may find a date for which you find no match later.

SELECT cT.* 
FROM cTable cT 
INNER JOIN (
  SELECT field_id, MAX(date_modified) AS date_modified
  FROM cTable 
  WHERE section_id = 123 
  GROUP BY field_id
) AS max USING (field_id, date_modified)
WHERE 
 cT.section_id = 123 AND
 cT.field_id=39;

Here is the SQL fiddle: http://www.sqlfiddle.com/#!2/0cefd8/19.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top