Порядок вывода пользовательских запросов с функцией CASE - PullRequest
2 голосов
/ 24 декабря 2011

Я часто нахожу, когда извлекаю данные для анализа, я группирую количество заказов, которые клиент разместил в диапазонах, например:

1-2
3-5
6-9
10-12
13-15

Я делаю это с помощью функции CASE. Однако, когда вы получите результаты запроса, диапазоны заказов будут перечислены как:

1-2
10-12
13-15
3-5
6-9

Это легко исправить в Excel, если у вас есть 1 запрос и несколько групп диапазонов заказов. Однако, когда вы выполняете много запросов, исправлять это снова и снова будет больно.

Каков наилучший способ вывести диапазон и правильно его упорядочить?

вот пример запроса, который я бы написал:

SELECT 
    OrderRange = CASE
        WHEN COUNT(OrderID) BETWEEN 1 AND 5 THEN '1-5'
        WHEN COUNT(OrderID) BETWEEN 6 AND 10 THEN '6-10'
        WHEN COUNT(OrderID) > 10 THEN '10+'
        ELSE 'Error'
    END
FROM Orders
GROUP BY CASE
    WHEN COUNT(OrderID) BETWEEN 1 AND 5 THEN '1-5'
    WHEN COUNT(OrderID) BETWEEN 6 AND 10 THEN '6-10'
    WHEN COUNT(OrderID) > 10 THEN '10+'
    ELSE 'Error'
    END
ORDER BY...  ?

Ответы [ 2 ]

3 голосов
/ 24 декабря 2011

Я бы вел таблицу диапазонов, например (индексы не написаны)

CREATE TABLE Ranges (RangeSet int, MinVal int, MaxVal int, Name varchar(50));

, а затем, например,

INSERT INTO ranges VALUES
  (1,1,5,'1-5'),(1,6,10,'6-10'),(1,11,-1,'11+'),
  (2,1,10,'1-10'),(2,11,20,'11-20'),(2,21,30,'21-30'),(2,31,-1,'31+');

Вы поняли идею. Теперь вы делаете что-то вроде (имена таблиц и полей без художественной литературы)

SELECT
  CustomerID,
  count(OrderID) AS OrderCount
FROM Orders
WHERE <whatever, e.g order_date BETWEEN ... AND ...>
GROUP BY CustomerID
HAVING OrderCount>0

как и следовало ожидать, но оберните его в суперзапрос, присоединяющийся к таблице Ranges

SELECT
  BaseView.CustomerID as CustomerID,
  Ranges.Name as OrderRange
FROM (
  SELECT
    CustomerID,
    count(OrderID) AS OrderCount
  FROM Orders
  WHERE <whatever, e.g order_date BETWEEN ... AND ...>
  GROUP BY CustomerID
  HAVING OrderCount>0
) AS BaseView
INNER JOIN Ranges ON
  Ranges.RangeSet=<id-of-required-rangeset>
  AND BaseView.OrderCount>=Ranges.MinVal
  AND (BaseView.OrderCount<=Ranges.MaxVal OR Ranges.MaxVal=-1)
ORDER BY RangeSet.MinVal DESC
;

Теперь вам нужно просто указать RangeSet, который вы хотите применить, возможно, создавая новый.

Отказ от ответственности: это убийца производительности

2 голосов
/ 24 декабря 2011

Если я правильно вас понимаю, вы хотите, чтобы список клиентов и диапазоны заказов были упорядочены от минимального до высокого.Вы должны быть в состоянии сделать это, просто упорядочив по количеству (orderID)

SELECT CustomerID,
    OrderRange = CASE
    WHEN COUNT(OrderID) BETWEEN 1 AND 5 THEN '1-5'
    WHEN COUNT(OrderID) BETWEEN 6 AND 10 THEN '6-10'
    WHEN COUNT(OrderID) > 10 THEN '10+'
    ELSE 'Error'
END ,
FROM Orders
GROUP BY CustomerID
order by count(orderid)

Результаты:

CustomerId  OrderRange
CENTC   1-5
GROSR   1-5
LAZYK   1-5
...
ROMEY   1-5
VINET   1-5
ALFKI   6-10
CACTU   6-10
...
VICTE   6-10

WANDK   6-10
BLONP   10+
GREAL   10+
RICAR   10+
...
QUICK   10+
ERNSH   10+
SAVEA   10+
...