Nano Hash - криптовалюты, майнинг, программирование

Добавить столбцы в SQL-запрос и фильтровать по минимуму (дате) и сумме (цене)

Я пытаюсь создать список пользователей, которые совершили первую покупку в декабре 2018 года и с тех пор потратили более 100 долларов на SQL. Я могу сгенерировать список пользователей, но я не могу определить, какой была их первая покупка или другие переменные, и, похоже, это проблема, поскольку столбцы, которые я пытаюсь включить, не сгруппированы и не агрегированы, поэтому я ' Я надеюсь, что кто-то может указать мне правильное направление, поскольку я новичок в SQL.

Вот мой код для создания списка, в который я хочу добавить больше столбцов:

select billing_address.name, contact_email, min(processed_at) as First_Purchase_Date, sum(total_price) as Total_Revenue

FROM (
  SELECT *, ROW_NUMBER() OVER(PARTITION BY id) AS instance
  FROM `table.orders`
) orders -- identify duplicate rows

WHERE instance = 1
group by contact_email, billing_address.name
having min(processed_at) between '2019-01-01 00:00:00 UTC' and '2019-02-01 00:00:00 UTC' and sum(total_price) > 100
order by sum(total_price) desc

Есть ли способ изменить это, чтобы вывести покупку каждого пользователя из этого списка в отдельную строку и включить больше столбцов? Поэтому я бы привлек каждого пользователя (и ВСЕ его покупки), у которого есть min(processed_at) в декабре 2018 г. И их sum(total_price) > 100? что-то вроде этого:

SELECT contact_email, billing_address, line_items, min(processed_at), sum(total_price) OVER (PARTITION BY contact_email)

FROM (
  SELECT *, ROW_NUMBER() OVER(PARTITION BY id) AS instance
  FROM `table.orders`
) orders -- identify duplicate rows

WHERE instance = 1

Однако sum(total_price) в этом случае не работает, и я не могу фильтровать по min(processed_at). Может ли кто-нибудь направить меня в правильном направлении?

13.11.2019

Ответы:


1

Я думаю, что вместо агрегации следует использовать оконные функции. Вы можете вычислить дату первой покупки и общую сумму, потраченную на лету в подзапросе, без агрегирования (ваши исходные group by столбцы становятся partition столбцами оконных функций). Затем вы можете использовать эту информацию для фильтрации во внешнем запросе.

Это должно приблизить вас к тому, что вы хотите:

select o.*
from (
    select 
        o.*,
        min(processed_at) over(partition by contact_email, billing_address) min_processed_at,
        sum(total_price)  over(partition by contact_email, billing_address) sum_total_price
    from (
        select 
            o.*,
            row_number() over(partition by id) instance
        from orders o
    ) o
    where instance = 1
) o
where 
    processed_at between '2019-01-01 00:00:00 UTC' and '2019-02-01 00:00:00 UTC'
    and sum_total_price > 100
14.11.2019
  • Не могли бы вы пояснить, что здесь означает «o»? Я не знаком с этой функцией. 14.11.2019
  • @ jerry2144: o не является функцией, это просто псевдоним для производной таблицы, которая создается каждым подзапросом. Это позволяет нам использовать что-то вроде o.* для ссылки на все столбцы, возвращаемые подзапросом. 14.11.2019

  • 2

    Ваш вопрос был немного неясным, поскольку вы не предоставили много подробностей о своих таблицах ввода или ожидаемом выходе, так что это предположение.

    Следующий запрос получает все транзакции от пользователей, которые соответствуют критериям:

    -- BigQuery StandardSQL
    
    with ordered_orders as (
    --rank each ID by processed_at date first to last
      select *, row_number() over(partition by id order by processed_at asc) as rn
      from `table.orders`
    ),
    first_criteria as (
    -- select IDs where first processed_at date is in 2018-12
      select id, processed_at as first_order_date
      from ordered_orders 
      where rn = 1 
        and extract(year from processed_at) = 2018
        and extract(month from processed_at) = 12
    ),
    second_criteria as (
    -- further select IDs who meet first criteria and have a total of > 100
      select id, sum(total_prices) as total_revenue
      from ordered_orders
      inner join first_criteria using(id)
      group by id
      having total_revenue > 100
    ),
    orders_with_criteria as (
    -- get all orders for users who meet both criteria
      select ordered_orders.* except(rn), first_order_date, total_revenue
      from ordered_orders
      inner join first_criteria using(id)
      inner join second_criteria using(id)
    ),
    -- select any fields you want
    select * from orders_with_criteria
    

    Я предпочитаю либеральное использование CTE в подобных случаях, чтобы логика была ясна.

    Я также не удивлюсь, если этот запрос не сработает так, как вы предполагали. Я думаю, очень сомнительно, что столбец ID в вашей orders таблице относится к клиенту id, на котором вы / мы разбиваем. В зависимости от того, кто настраивал ваши столы, id, вероятно, относится к порядку id. Если у вас есть customer_id (или номер счета и т. Д.), Я бы использовал его вместо id в запросе.

    14.11.2019

    3

    Для этого не нужно использовать row_number() в BigQuery:

    SELECT billing_address.name, contact_email, 
           MIN(processed_at) as First_Purchase_Date, 
           SUM(total_price) as Total_Revenue,
           ARRAY_AGG(o ORDER BY processed_at LIMIT 1) as first_order
    FROM `table.orders` o
    WHERE instance = 1
    GROUP BY contact_email, billing_address.name
    HAVING MIN(processed_at) >= '2019-01-01 00:00:00 UTC' AND
           MIN(processed_at) < '2019-02-01 00:00:00 UTC' AND
           SUM(total_price) > 100
    ORDER BY SUM(total_price) desc;
    

    Это возвращает весь первый заказ в виде структуры. При желании вы можете выбрать определенные столбцы.

    14.11.2019
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..