diff -r 9a98f1529cd3 nuxeo-core-storage-sql/nuxeo-core-storage-sql-test/src/test/java/org/nuxeo/ecm/core/storage/sql/TestSQLRepositoryQuery.java
--- a/nuxeo-core-storage-sql/nuxeo-core-storage-sql-test/src/test/java/org/nuxeo/ecm/core/storage/sql/TestSQLRepositoryQuery.java	Sat May 16 22:10:06 2009 +0200
+++ b/nuxeo-core-storage-sql/nuxeo-core-storage-sql-test/src/test/java/org/nuxeo/ecm/core/storage/sql/TestSQLRepositoryQuery.java	Thu Sep 10 10:26:18 2009 +0200
@@ -17,6 +17,7 @@
 
 package org.nuxeo.ecm.core.storage.sql;
 
+import org.nuxeo.ecm.core.api.DocumentModelList;
 import org.nuxeo.ecm.core.query.test.QueryTestCase;
 
 /**
@@ -52,4 +53,26 @@
         super.testFulltextBlob();
     }
 
+    public void testMultiSortQuery() throws Exception {
+        DocumentModelList dml;
+        createDocs();
+
+        dml = session.query("SELECT * FROM Document ORDER BY ecm:primaryType ASC, ecm:name ASC");
+        assertEquals("testfile1_Title", dml.get(0).getPropertyValue("dc:title")); // first
+                                                                                  // File
+        assertEquals("testfolder1_Title", dml.get(3).getPropertyValue(
+                "dc:title")); // first Folder
+
+        dml = session.query("SELECT * FROM Document ORDER BY ecm:primaryType DESC, ecm:name ASC");
+        assertEquals("testfile3_Title", dml.get(0).getPropertyValue("dc:title")); // a
+                                                                                  // Note
+        assertEquals("testfile1_Title", dml.get(4).getPropertyValue("dc:title")); // first
+                                                                                  // File
+
+        dml = session.query("SELECT * FROM Document ORDER BY ecm:primaryType ASC, ecm:name DESC");
+        assertEquals("testfile4_Title", dml.get(0).getPropertyValue("dc:title"));
+        assertEquals("testfolder1_Title", dml.get(5).getPropertyValue(
+                "dc:title"));
+    }
+
 }
diff -r 9a98f1529cd3 nuxeo-core-storage-sql/nuxeo-core-storage-sql/src/main/java/org/nuxeo/ecm/core/storage/sql/QueryMaker.java
--- a/nuxeo-core-storage-sql/nuxeo-core-storage-sql/src/main/java/org/nuxeo/ecm/core/storage/sql/QueryMaker.java	Sat May 16 22:10:06 2009 +0200
+++ b/nuxeo-core-storage-sql/nuxeo-core-storage-sql/src/main/java/org/nuxeo/ecm/core/storage/sql/QueryMaker.java	Thu Sep 10 10:26:18 2009 +0200
@@ -165,6 +165,16 @@
      */
     protected String joinedHierId;
 
+    private QueryAnalyzer info;
+
+    private Select select;
+
+    private WhereBuilder whereBuilder;
+
+    private String mainWhat;
+
+    private final List<String> mainJoins = new ArrayList<String>();
+
     public QueryMaker(SQLInfo sqlInfo, Model model, Session session,
             SQLQuery query, QueryFilter queryFilter) {
         this.sqlInfo = sqlInfo;
@@ -202,7 +212,7 @@
         private static final long serialVersionUID = 1L;
     }
 
-    public void makeQuery() throws StorageException {
+    public void makeSubQuery() throws StorageException {
         // clauses ANDed together
         List<String> whereClauses = new LinkedList<String>();
 
@@ -210,7 +220,7 @@
          * Find all relevant types and keys for the criteria.
          */
 
-        QueryAnalyzer info = new QueryAnalyzer();
+        info = new QueryAnalyzer();
         try {
             info.visitQuery(query);
         } catch (QueryCannotMatchException e) {
@@ -431,7 +441,7 @@
          * actual WHERE clauses and potential JOINs.
          */
 
-        WhereBuilder whereBuilder;
+
         try {
             whereBuilder = new WhereBuilder();
         } catch (QueryMakerException e) {
@@ -450,6 +460,44 @@
             }
         }
 
+
+        /*
+         * Check if we need a DISTINCT.
+         */
+
+        String what = hierId;
+        boolean useAlias= false;
+        if (considerProxies) {
+            // For proxies we do a LEFT JOIN with a non equi-join
+            // condition that can return two rows.
+            useAlias = true;
+            what = "DISTINCT " + what;
+        }
+
+        mainWhat = what;
+
+        // else no DISTINCT needed as all impacted tables have unique keys
+
+        /*
+         * Create the whole select.
+         */
+        select = new Select(null);
+        select.setWhat(what);
+        select.setFrom(StringUtils.join(joins, " LEFT JOIN "));
+        select.setWhere(StringUtils.join(whereClauses, " AND "));
+
+    }
+
+    public void makeQuery() throws StorageException {
+        makeSubQuery();
+        if (select == null) {
+            return; // Contradictory clauses in select
+        }
+        List<Column> whatColumns = Collections.singletonList(hierTable.getColumn(model.MAIN_KEY));
+
+        List<String> whereClauses = new ArrayList<String>();
+        whereClauses.add(hierId + " IN (" + select.getStatement() + ")" );
+
         /*
          * Security check.
          */
@@ -471,6 +519,46 @@
         }
 
         /*
+         * Create the FROM for the main select.
+         */
+
+        boolean useAlias = false;
+        Table hier = database.getTable(model.hierTableName);
+        if (considerProxies) {
+            useAlias = true;
+            String alias = dialect.storesUpperCaseIdentifiers() ? "_NXHIER"
+                    : "_nxhier";
+            hierTable = new TableAlias(hier, alias);
+            joinedHierTable = hierTable;
+            mainJoins.add(hier.getQuotedName() + " "
+                    + hierTable.getQuotedName()); // TODO dialect
+        } else {
+            // simple case where we directly refer to the hierarchy table
+            mainJoins.add(hierTable.getQuotedName());
+        }
+
+        // Some dialects need any ORDER BY expressions to appear in the
+        // SELECT list when using DISTINCT.
+        Set<Column> columns = new HashSet<Column>();
+        if (dialect.needsOrderByKeysAfterDistinct()) {
+            for (String key : info.orderKeys) {
+                Column column = findColumn(key, false, true);
+                String qname = column.getFullQuotedName();
+                mainWhat += ", " + qname;
+                if (!hierTable.getName().equals(column.getTable().getName())) {
+                    columns.add(column);
+                }
+            }
+            for (Column column : columns) {
+                mainJoins.add(String.format("%s ON %s = %s",
+                        column.getTable().getQuotedName(), useAlias ? hierId
+                                : joinedHierId, column.getTable().getColumn(
+                                model.MAIN_KEY).getFullQuotedName()));
+            }
+        }
+
+
+        /*
          * Order by.
          */
 
@@ -483,38 +571,14 @@
             orderBy = whereBuilder.buf.toString();
         }
 
-        /*
-         * Check if we need a DISTINCT.
-         */
 
-        String what = hierId;
-        if (considerProxies) {
-            // For proxies we do a LEFT JOIN with a non equi-join
-            // condition that can return two rows.
-            what = "DISTINCT " + what;
-            // Some dialects need any ORDER BY expressions to appear in the
-            // SELECT list when using DISTINCT.
-            if (dialect.needsOrderByKeysAfterDistinct()) {
-                for (String key : info.orderKeys) {
-                    Column column = findColumn(key, false, true);
-                    String qname = column.getFullQuotedName();
-                    what += ", " + qname;
-                }
-            }
-        }
-        // else no DISTINCT needed as all impacted tables have unique keys
+        Select mainSelect = new Select(null);
+        mainSelect.setWhat(mainWhat);
+        mainSelect.setFrom(StringUtils.join(mainJoins, " LEFT JOIN "));
+        mainSelect.setWhere("(" + StringUtils.join(whereClauses, " AND ") + ")");
+        mainSelect.setOrderBy(orderBy);
 
-        /*
-         * Create the whole select.
-         */
-        Select select = new Select(null);
-        select.setWhat(what);
-        select.setFrom(StringUtils.join(joins, " LEFT JOIN "));
-        select.setWhere(StringUtils.join(whereClauses, " AND "));
-        select.setOrderBy(orderBy);
-
-        List<Column> whatColumns = Collections.singletonList(hierTable.getColumn(model.MAIN_KEY));
-        selectInfo = new SQLInfoSelect(select.getStatement(), whatColumns,
+        selectInfo = new SQLInfoSelect(mainSelect.getStatement(), whatColumns,
                 null, null);
     }
 
