I've seen a number of answers prescribing how to sort across different sections...but I'm not seeing it work. Here's what I've tried:

{% set profileIds = craft.entries.section('profiles').order('profileBorn asc').ids() %}
{% set eventIds = craft.entries.section('events').order('eventDate asc').ids() %}
{% set timelineIds = profileIds|merge(eventIds) %}
{% set timeline = craft.entries.id(timelineIds) %}


{% set timeline = craft.entries.section(['profiles','events']).order('GREATEST(eventDate, profileBorn) desc') %}

Then for either, I'm doing:

{% for entry in timeline %}

In both cases, I get entries in the following order, with their {{ entry.profileBorn }} or {{ entry.eventDate }} shown here:

  • 1832-02-01 / events entry
  • 1830-01-01 / profiles entry
  • 1840-01-01 / profiles entry

Any thoughts? Thanks!


This looks like the SQL being generated by the first answer's suggestion, which is still outputting the event entry first.

SELECT `elements`.`id`, `elements`.`type`, `elements`.`enabled`, `elements`.`archived`, `elements`.`dateCreated`, `elements`.`dateUpdated`, `elements_i18n`.`slug`, `elements_i18n`.`uri`, `elements_i18n`.`enabled` AS `localeEnabled`, `content`.`id` AS `contentId`, `content`.`title`, `content`.`field_profileBio`, `content`.`field_body`, `content`.`field_profileBorn`, `content`.`field_copyright`, `content`.`field_datePrecision`, `content`.`field_datePrecisionBorn`, `content`.`field_datePrecisionDied`, `content`.`field_profileDied`, `content`.`field_eventDate`, `content`.`field_mediaCaption`, `content`.`field_mediaPublicationDate`, `content`.`field_mediaSource`, `content`.`field_mediaTitle`, `content`.`field_siteTitle`, `entries`.`sectionId`, `entries`.`typeId`, `entries`.`authorId`, `entries`.`postDate`, `entries`.`expiryDate`, `structureelements`.`root`, `structureelements`.`lft`, `structureelements`.`rgt`, `structureelements`.`level` FROM `craft_elements` `elements` JOIN `craft_elements_i18n` `elements_i18n` ON elements_i18n.elementId = elements.id JOIN `craft_content` `content` ON content.elementId = elements.id JOIN `craft_entries` `entries` ON entries.id = elements.id JOIN `craft_sections` `sections` ON sections.id = entries.sectionId LEFT JOIN `craft_structures` `structures` ON structures.id = sections.structureId LEFT JOIN `craft_structureelements` `structureelements` ON (structureelements.structureId = structures.id) AND (structureelements.elementId = entries.id) WHERE (((((elements_i18n.locale = :locale) AND (content.locale = :locale)) AND ((elements.id=:elementsid1) OR (elements.id=:elementsid2) OR (elements.id=:elementsid3))) AND (elements.archived = 0)) AND ((elements.enabled = 1) AND (elements_i18n.enabled = 1) AND (entries.postDate <= '2017-07-12 12:47:25') AND ((entries.expiryDate is null) OR (entries.expiryDate > '2017-07-12 12:47:25')))) AND (elements_i18n.enabled = 1) GROUP BY `elements`.`id` ORDER BY GREATEST(field_eventDate, field_profileBorn) asc LIMIT 100


Your second attempt is sound. I don’t really have an idea why it doesn’t work, but I bet it has to do with the SQL that is caused by setting the section param to an array.

What I would try next is the following, kind of a merge of your ideas.

{% set profileIds = craft.entries.section('profiles').limit(null).ids() %}
{% set eventIds = craft.entries.section('events').limit(null).ids() %}

{% set idParam = profileIds|merge(eventIds) %}

{% set timeline = craft.entries({
    id: idParam,
    order: 'GREATEST(eventDate, profileBorn) desc',
}) %}
  • Thanks for the reply! Same thing happens with the code you provided. Jul 12 '17 at 12:42
  • I pasted in the SQL being generated there. Jul 12 '17 at 12:49
  • Sorry but I don’t really have an idea why that happens.
    – carlcs
    Jul 12 '17 at 14:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.