Как упорядочить SQL-запрос со сгруппированными строками

У меня есть таблица (Product_Id, приоритет категории, атрибут1, атрибут2...) в MS Access, и я пытаюсь сделать запрос, который упорядочивает данные, сгруппированные по категориям и упорядоченные по наивысшему приоритету. Приоритет может быть нулевым, поэтому его следует поместить в конец. Пример: Таблица

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

Ожидаемый результат в запросе:

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

person Community    schedule 22.12.2008    source источник


Ответы (5)


В Jet SQL это может подойти:

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);
person Fionnuala    schedule 22.12.2008
comment
ба, ты меня просто опередил :) Вопрос о твоей "таблице" во внутреннем объединении значительно сложнее, чем в примере, который я использовал. Я не уверен, что это должно быть. - person Ron Tuffin; 22.12.2008
comment
Я работал с полями ZLS not Null из вырезания и вставки :(. Я исправил это. - person Fionnuala; 22.12.2008
comment
В Jet SQL это может подойти — нет, потому что Jet SQL не поддерживает функцию NZ(). Вы должны были сказать: В MS Access... или аналогичном, потому что функция NZ() предоставляется интерфейсом MS Access. В Jet за пределами интерфейса MS Access ваши ошибки SQL: неопределенная функция «NZ» в выражении. - person onedaywhen; 05.01.2009
comment
Это правда. Возможно, Jet использовался с Access? - person Fionnuala; 07.01.2009
comment
Лучше использовать IIF([Field3] IS NULL, 999, [Field3]), поскольку он будет работать как в Jet, так и в MS Access и позволяет избежать известных проблем с типизацией данных (что влияет на сортировку) с помощью NZ(). О других причинах см. allenbrowne.com/QueryPerfIssue.html. - person onedaywhen; 08.01.2009

Самое простое решение (не обязательно лучшее в некоторых случаях) — использовать номера столбцов в ваших выражениях заказа:

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

ORDER BY 1,2,3
person Einstein    schedule 05.01.2009

Вам нужно взвесить категории (я взвешиваю нуль с некоторым достаточно большим значением):

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)   
person Unsliced    schedule 22.12.2008
comment
MS Jet этого не поймет. - person Tomalak; 22.12.2008
comment
На самом деле вам нужно заказать по t2.weight desc и использовать isnull(t1.priority,0) и max() - или как я понимаю исходный вопрос :) - person Arvo; 22.12.2008
comment
Jet не поддерживает COALESCE или ISNULL. - person onedaywhen; 22.12.2008
comment
ISNULL можно заменить на Nz() в Jet SQL, не так ли? Я не верю, что в Jet SQL есть какая-то команда COALESCE. - person David-W-Fenton; 23.12.2008
comment
На самом деле нет, NZ() не является родным синтаксисом Jet SQL. NZ() предоставляется объектной моделью MS Access и поэтому доступен только в запросах через интерфейс MS Access. Родной Jet должен использовать IIF, который, по мнению Аллена Брауна, в любом случае превосходит NZ() (allenbrowne.com/QueryPerfIssue .html) - person onedaywhen; 02.01.2009

Насколько мне известно, Jet всегда сортирует NULL в конец результирующего набора, когда используется явный ORDER BY.

См. Свойства и настройки поставщика ADO.

NULL Collation Order: длинное значение (только для чтения), указывающее, где нулевые значения сопоставляются (сортируются). Для поставщика Microsoft Jet значение всегда равно 4, что указывает на то, что нулевые значения сортируются в нижнем конце списка. ."

Тот факт, что свойство NULL Collation Order доступно только для чтения для провайдера, убедительно свидетельствует о том, что движок Jet имеет только одну NULL-систему сортировки, и, к счастью для вас, это именно то, что вам нужно.

person onedaywhen    schedule 22.12.2008
comment
Если нулевые значения отсортированы в нижней части списка, то нулевые значения появятся в списке первыми. это противоречит вопросу, где в конце должен быть помещен нуль. - person Ron Tuffin; 22.12.2008
comment
Рон, похоже, ты неверно истолковал значение нижней части списка. Ключевое слово здесь — конец. Подумайте о наборе записей: значения NULL будут отсортированы по позициям, ближайшим к EOF (конец файла). Вы тестировали его с Jet? Попробуйте, и я думаю, вы согласитесь, что NULL не появляются первыми. - person onedaywhen; 02.01.2009

Очевидно NZ(Value, ValueToReturnIfNull) можно использовать в MSAccess вместо ISNULL, поэтому ...

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)
person Ron Tuffin    schedule 22.12.2008
comment
Большое спасибо, Рон, но это еще не работает полностью. Он отлично работает, если определены приоритеты. Если существует более одной категории без приоритета, эти категории не группируются. - person ; 22.12.2008
comment
Я не уверен, что следую. Вышеупомянутое должно привести к тому, что любая категория, имеющая только приоритет NULL, опустится на дно. Если вы хотите отсортировать эти категории (с приоритетами только NULL) между собой, добавьте a.category в конец предложения ORDER BY. Дайте мне знать, я буду обновлять. - person Ron Tuffin; 22.12.2008
comment
еще раз спасибо, Рон, вот и все, я добавил a.category после b.min_priority_in_cat, и все работает отлично. Я узнал об этом от Remou (tn.Field2). Спасибо за вашу помощь! - person ; 22.12.2008
comment
NZ(Value, ValueToReturnIfNull) можно использовать в jet вместо ISNULL — Рон, в Jet нет функции NZ(). Однако MS Access делает это. - person onedaywhen; 02.01.2009