Как группировать по дням / месяцам / годам в CosmosDB SQL-API

#python #sql #group-by #azure-cosmosdb

#питон #sql #групповое-по #azure-cosmosdb

Вопрос:

Я хотел бы создать функцию, способную группировать мои данные в Cosmos DB на основе дня, месяца или года. У меня уже есть исполняющая команда в pandas. Я бы хотел сделать то же самое.

 df = pd.DataFrame(
    [
    {'date': '27/06/2020 12:49', 'labels': 0, 'code': 1},
    {'date': '27/06/2020 17:10', 'labels': 0, 'code': 3},
    {'date': '22/06/2020 09:02', 'labels': 0, 'code': 3},
    {'date': '22/06/2020 10:38', 'labels': 1, 'code': 1},
    {'date': '22/06/2020 21:50', 'labels': 1, 'code': 3},
    {'date': '25/06/2020 00:46', 'labels': 1, 'code': 1}
    ]
)

df['date'] = pd.to_datetime(df['date'], format='%d/%m/%Y %H:%M')
df.groupby(pd.Grouper(key='date',freq='D')).agg({'label':'sum', 'code':'count'})
 

введите описание изображения здесь

Я уже пробовал разные способы сделать это в Cosmos, но результаты странные. Вот мой запрос с соответствующими результатами:

 'SELECT DateTimePart("D", r.data_ora_inserimento_preventivo), r.labels, r.sorgente_dati, count(1) FROM mycontainer r group by DateTimePart("D", r.data_ora_inserimento_preventivo), r.labels, r.sorgente_dati'

{'labels': 0, 'code': '3', '$2': 16236}
{'labels': 1, 'code': '3', '$2': 286}
{'labels': 0, 'code': '3', '$2': 16534}
{'labels': 1, 'code': '3', '$2': 187}
{'labels': 0, 'code': '3', '$2': 15726}
{'labels': 1, 'code': '3', '$2': 161}
{'labels': 0, 'code': '3', '$2': 15854}
{'labels': 1, 'code': '3', '$2': 177}
{'labels': 0, 'code': '3', '$2': 15405}
{'labels': 1, 'code': '3', '$2': 164}
{'labels': 0, 'code': '3', '$2': 15723}
{'labels': 1, 'code': '3', '$2': 304}
{'labels': 1, 'code': '3', '$2': 447}
{'labels': 0, 'code': '3', '$2': 3012}
 

Ответ №1:

DateTimePart вернет undefined по следующим причинам:

Указанное значение DateTimePart недопустимо

Дата-время не является допустимым значением даты-времени ISO 8601

Ваша дата не является допустимой датой времени ISO 8601, что приводит к странным результатам. Итак, вам нужно преобразовать вашу дату в формат ISO. Вы можете добиться этого с помощью UDF. Затем попробуйте что-то вроде этого SQL:

 SELECT 
    left(udf.casttoISO(c.date),10) as date, sum(c.labels) as labels, count(c.code) as code 
FROM c 
group by left(udf.casttoISO(c.date),10) 
 

Результат:

 [
    {
        "date": "2020-06-25",
        "labels": 1,
        "code": 1
    },
    {
        "date": "2020-06-22",
        "labels": 2,
        "code": 3
    },
    {
        "date": "2020-06-27",
        "labels": 0,
        "code": 2
    }
]
 

Кстати, DateTimePart функция не будет использовать индекс, поэтому я думаю Left , что функция будет лучше.


Обновить:

1. Вы можете создать UDF на портале. Что касается UDF, вы можете обратиться к этому MSDN. введите описание изображения здесь

2. В вашем комментарии упоминается, что вы используете Python SDK. К сожалению, когда вы запустите приведенный выше SQL, вы получите следующее сообщение об ошибке:

(Неверный запрос) Шлюзу не удалось получить план запроса: запрос содержит 1 или более неподдерживаемых функций. Обновите свой SDK до версии, которая поддерживает запрошенные функции: Запрос содержал GroupBy, который вызывающий клиент не поддерживает.

Потому что Python SDK на данный момент не Group BY поддерживается. Они планируют добавить эту функцию в этом году. Вы можете обратиться к этому. Если вы хотите выполнить приведенный выше SQL, вы можете запустить его на портале, используя .NET SDK или JS SDK.

Комментарии:

1. Я попробовал ваше решение, но получил вот что: CosmosHttpResponseError: (BadRequest) Message: {"Errors":["The input user defined function 'casttoISO' is not present in the collection. Ensure to pass a valid function identifier."]} . Это проблема с удаленным пакетом или просто функция, которую Cosmos не поддерживает?

2. @el_Rinaldo Вы создали UDF в своей коллекции?

3. Я действительно установил PySpark. Включает ли он udf, не так ли? Это и есть импорт: from pyspark.sql.functions import udf

4. @el_Rinaldo Я обновляю свой ответ, вы можете посмотреть.