SQL Найти минимальное число для каждого значения в аналитической функции - PullRequest
0 голосов
/ 18 сентября 2018

Я использую Microsoft SQL Server.Я хочу написать запрос только с аналитической функцией (например, не используя group by)

Я хочу написать запрос, который возвращает строки:

  • MIN (Customer_number), count (код), частный
  • MIN (Customer_number), count (код), бизнес

Я сделал две таблицы, например

enter image description here

в этом примере Customer_number = 1,2 должен быть только для строк следующим образом:

* 1,intermediate results counting,private
.
.
.
* 2, intermediate results counting, business
.
.
.

Я написал:

SELECT 
    MIN(subscribers.customer_number) OVER (PARTITION BY customers.customer_number, customer_type) AS cusNo,
    COUNT(subscribers.code) OVER (PARTITION BY customers.customer_number, customer_type) AS subscribes,
    customer_type
FROM
    customers 
JOIN
    subscribers ON subscribers.customer_number = customers.customer_number;

Я пытался понять так много временикак вернуть правильный вывод, почему он не работает и не может его найти

Если бы кто-нибудь мог помочь мне с тем, как его заказать, и объяснить, что не так, это было бы здорово.

1 Ответ

0 голосов
/ 18 сентября 2018

Похоже, вам нужны только клиенты 1 и 2, что, как я понимаю, означает, что вы хотите, чтобы только частный клиент с наименьшим номером, а также бизнес-клиент с наименьшим номером.

Вы не хотите использовать группирование по.

SELECT * FROM
  (
    SELECT
      --number each row, order by customer number, "group" by business type 
      ROW_NUMBER() OVER(PARTITION BY c.customer_type ORDER BY c.customer_number) rown, 
      --it isn't totally clear if you want the count of codes per customer or per type
      count(s.code) OVER (partition by c.customer_number) AS count_codes_by_cust,
      count(s.code) OVER (partition by c.customer_type) AS count_codes_by_type,
      customer_type 
    FROM
      customers c 
      INNER JOIN
      subscribers s
      ON s.customer_number = c.customer_number
  ) c
WHERE rown = 1 --cust #1 and cust#2 both have a rown of 1

Обратите внимание, что я оставил соединение подписчикам и подсчитывал коды для этого, для ясности - критическая концепция, что вашПервоначальная попытка отсутствовала при использовании WHERE, чтобы ограничить вывод только двумя строками

Ваша первая попытка также может быть изменена для получения требования:

SELECT * FROM
(
 SELECT 
  min(c.customer_number) OVER (partition by c.customer_type) AS min_cust,
  c.customer_number,
  --it isn't totally clear if you want the count of codes per customer or per type
  count(s.code) OVER (Partition by c.customer_number) AS count_codes_by_cust,
  count(s.code) OVER (Partition by c.customer_type) AS count_codes_by_type,
  customer_type
 FROM 
  customers c 
  INNER JOIN
  subscribers s
  ON s.customer_number = c.customer_number
)d
WHERE
  min_cust = customer_number

Но недостаток этого подхода заключается в том, чтоон дает несколько строк, потому что объединение клиентов и подписчиков приводит к тому, что номер клиента повторяется, и в результате получается более одной строки, где where min_cust = customer number истинно: min (customer_number) over (...) выбрало «1»и «2» в качестве минимального числа клиентов, но благодаря соединению с подписчиками 1 появляется 3 раза, а 2 - дважды

Подход row_number отличается в этом отношении = только одна строка на customer_type может иметьномер строки 1, поэтому вы получите только столько строк, сколько у вас разных типов клиентов.В более общем плане, если у вас есть таблица, в которой хранятся, например, несколько датированных версий документа, и вам нужна только последняя версия каждого документа, вы можете:

SELECT * FROM (
  SELECT 
    doc.*, 
    ROW_NUMBER() OVER(PARTITION BY filename ORDER BY filedate DESC) --latest is numbered 1
  FROM
    documents
)doc WHERE rown = 1

Чтобы просмотреть действиеболее подробно выделите и выполните только внутренние запросы, чтобы посмотреть необработанные данные, над которыми работает внешний запрос.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...