views:

901

answers:

5

I have the table (Product_Id, category priority, atribute1, atribute2...) in MS Access, and I am trying to make a query that orders the data grouped by Category and ordered by the highest priority. Priority can be Null, so it should be placed at the end. Example: Table

1, 100, 2, atr1, atr2
2, 300,  , atr1, atr2
3, 100, 5, atr1, atr2
4, 200, 9, atr1, atr2
5, 100,  , atr1, atr2
6, 200, 1, atr1, atr2

Result expected in Query:

6, 200, 1, atr1, atr2
4, 200, 9, atr1, atr2
1, 100, 2, atr1, atr2
3, 100, 5, atr1, atr2
5, 100,  , atr1, atr2
2, 300,  , atr1, atr2
A: 

You need to weight the categories (I'm weighting null with some suitably large value):

select  t1.* 
from    myTable t1 
join 
( 

    select  category, min(coalesce(priority, 1000)) weight
    from    myTable 
    group by category
) t2 
on t1. category = t2. category
order by t2.weight, coalesce(t1. priority, 1000)
Unsliced
MS Jet won't understand this.
Tomalak
try isnull(priority, 1000)
Ron Tuffin
Actually you need "order by t2.weight desc" and use "isnull(t1.priority,0)" and max() - or how I understand original question :)
Arvo
Jet doesn't support COALESCE or ISNULL.
onedaywhen
ISNULL can be replaced with Nz() in Jet SQL, no? I don't believe there's any command to COALESCE in Jet SQL.
David-W-Fenton
Actually, no, NZ() is not native Jet SQL syntax. NZ() is provided by the MS Access object model and therefore only available in queries via the MS Access interface. The native Jet is to use IIF, which FWIW Allen Browne reckons is superior to NZ() anyhow (http://allenbrowne.com/QueryPerfIssue.html)
onedaywhen
A: 

As far as I know, Jet always sorts NULLs to the end of a resultset when an explicit ORDER BY is used.

See: ADO Provider Properties and Settings

"NULL Collation Order: A Long value (read-only) that specifies where Null values are collated (sorted). For the Microsoft Jet provider, the value is always 4, which indicates that null values are sorted at the low end of the list."

The fact the property NULL Collation Order is read-only for the provider strongly suggests the Jet engine has only one NULL collation and, happily for you, it's the one you desire.

onedaywhen
If "null calues are sorted at the low end of the list" then teh nulls will appear first on the list. this is contrary to the question where null "should be placed at the end".
Ron Tuffin
Ron, you seem to have misinterpreted the meaning of "low end of the list". The key word here is "end". Think of a recordset: the NULLs will be sorted to the positions nearest the EOF (*end* of file). Did you test it with Jet? Try it and I think you'll agree that the NULLs do not appear first.
onedaywhen
+2  A: 

In Jet SQL, this may suit:

SELECT t2.MinOfPriority, tn.Field2, Nz([tn.Field3],999) AS Priority, 
       tn.Field4, tn.Field5
FROM tn 
INNER JOIN (SELECT Min(Nz(tn.Field3,999)) AS MinOfPriority, tn.Field2
            FROM  tn GROUP BY tn.Field2) AS t2 ON tn.Field2 = t2.Field2
ORDER BY t2.MinOfPriority, tn.Field2, Nz([Field3],999);
Remou
bah you just beat me :) Question your 'table' in the inner join is significantly more complicated than the example I used. I'm not sure it needs to be.
Ron Tuffin
I was working with ZLS not Null fields from cut-and-paste :( . I have corrected it.
Remou
"In Jet SQL, this may suit" - no, because Jet SQL does not support the NZ() function. You should have said, "In MS Access..." or similar because the NZ() function is provided by the MS Access interface. In Jet outside of the MS Access interface your SQL errors: Undefined function 'NZ' in expression.
onedaywhen
That is true. "Jet used with Access " perhaps?
Remou
Better is IIF([Field3] IS NULL, 999, [Field3]) because it will work in both Jet and MS Access and avoids known issues with data typing (which affects sorting) with NZ(). For other reasons, see http://allenbrowne.com/QueryPerfIssue.html.
onedaywhen
A: 

Apparently NZ(Value, ValueToReturnIfNull) can be used on MSAccess as a substitute for ISNULL so ...

SELECT a.*
FROM this_table AS a 
    INNER JOIN 
    (
        SELECT category,min(NZ(priority,999999)) as min_priority_in_cat 
        FROM this_table group by category
    ) AS b ON a.category = b.category
ORDER BY  b.min_priority_in_cat, a.category, NZ(a.priority,999999)
Ron Tuffin
Thanks a lot Ron, but it does not work completely yet. It works perfectly if there are Priorities defined. As soon as there is more than one Category without Priority then these Categories are not grouped.
I'm not sure I follow. The above should result in any category that has only a NULL priority sink to the bottom. If you want to sort these categories (the ones with only NULL as priorities) amongst themselves then add a a.category to the end of the ORDER BY clause.Let me know, I will then update.
Ron Tuffin
thanks again Ron, that was it, I added the a.category after b.min_priority_in_cat and works perfect. I found it out from Remou (tn.Field2). Thanks for your help!
"NZ(Value, ValueToReturnIfNull) can be used on jet as a substitute for ISNULL" - Ron, Jet does not have an NZ() function. MS Access does, though.
onedaywhen
+1  A: 

The easiest solution (not necessarily the best in some cases) is to use column numbers in your ordering expressions:

SELECT t2.MinOfPriority, tn.Field2, Nz([tn.Field3],999) AS Priority, tn.Field4, tn.Field5

ORDER BY 1,2,3

Einstein