#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 Я обновляю свой ответ, вы можете посмотреть.