SQL для csv-файла с помощью bash или оболочки

Хотя вопрос предполагает опрос мнений, который противоречит политике вопроса stackexchange , я постараюсь привести некоторые причины, которые, конечно, предвзяты.

  • это бесплатно (конечно, вы можете купить услуги поддержки корпоративного уровня у разных компаний, если хотите);
  • это открытый исходный код
  • он гораздо менее подвержен вирусным инфекциям (гораздо меньше векторов для атак, поэтому вы нет необходимости запускать аудио / видео программное обеспечение, которое отслеживает активность программ во время выполнения) по сравнению с некоторыми другими операционными системами и связанным с ними программным обеспечением.
  • он очень хорошо управляем, масштабируем и расширяем.

И, наконец, ответ на последний вопрос, который вы выделили жирным шрифтом.

Не рекомендуется. Каждая вещь обслуживает чьи-то потребности с определенным качеством за определенные деньги. Баланс качества и стоимости имеет значение.

-1
13.03.2019, 20:17
4 ответа

Использованиеcsvkit:

csvsql -H --query "select a,min(b),max(c),d from file group by a,d" file.csv

Обратите внимание, что это усекает начальный 0.

Выход:

a,min(b),max(c),d
164318,1449,1457,1922
841422,1221,1228,1860
842179,2115,2118,1485
846354,1512,1513,1590
4
28.01.2020, 05:06

Использование csvkit,

$ csvsql -H --query 'SELECT a,min(b),max(c),d FROM file GROUP BY a' file.csv
a,min(b),max(c),d
164318,1449,1457,1922
841422,1221,1228,1860
842179,2115,2118,1485
846354,1512,1513,1590

Это загрузит данные CSV во временную базу данных (SQLite по умолчанию, я полагаю ), а затем применит к ней заданный SQL-запрос. По умолчанию таблица будет иметь то же имя, что и входной файл (без суффикса ), и, поскольку в данных отсутствуют заголовки столбцов, имена полей по умолчанию будут в алфавитном порядке.

Опции -Hсообщают csvsql, что данные не имеют заголовков столбцов.

Чтобы удалить сгенерированный заголовок в выводе, передайте результат через что-то вроде sed '1d'.

Для получения нуля -заполненных целых чисел:

$ csvsql -H --query 'SELECT printf("%07d,%06d,%06d,%06d",a,min(b),max(c),d) FROM file GROUP BY a' file.csv
"printf(""%07d,%06d,%06d,%06d"",a,min(b),max(c),d)"
"0164318,001449,001457,001922"
"0841422,001221,001228,001860"
"0842179,002115,002118,001485"
"0846354,001512,001513,001590"

Здесь строки заключены в кавычки, так как на самом деле мы запрашиваем только одно поле вывода для каждой записи результата (и оно содержит запятые ). Другой способ сделать это, который включает в себя немного больше ввода, но не создает дополнительных двойных кавычек:

$ csvsql -H --query 'SELECT printf("%07d",a),printf("%06d",min(b)),printf("%06d",max(c)),printf("%06d",d) FROM file GROUP BY a' file.csv
"printf(""%07d"",a)","printf(""%06d"",min(b))","printf(""%06d"",max(c))","printf(""%06d"",d)"
0164318,001449,001457,001922
0841422,001221,001228,001860
0842179,002115,002118,001485
0846354,001512,001513,001590

Опять же, выходной заголовок можно удалить, передав результат через sed '1d'.

6
28.01.2020, 05:06

С Миллером (http://johnkerl.org/miller/doc), используя

mlr --ocsv --quote-all --inidx --ifs, cat inputFile | \
mlr --ocsv --quote-none  --icsvlite stats1 -g '"1"' -a min,max,min -f '"2","3","4"' \
then cut -f '"1","2"_min,"3"_max,"4"_min' \
then label id,col2,col3,col4 | sed 's/"//g'

у вас есть

id,col2,col3,col4
0164318,001449,001457,001922
0842179,002115,002118,001485
0846354,001512,001513,001590
0841422,001221,001228,001860
1
28.01.2020, 05:06

Вы можете разбить свой SQL на базовые процедурные операции и воспроизвести их в сценарии оболочки.

Это, конечно, не очень хорошая идея, поскольку одно из преимуществ декларативных языков (, таких как SQL ), заключается в том, что они скрывают от разработчиков многословие и сложность процедурной реализации, позволяя им сконцентрироваться на данных. (Оптимизация — второе большое преимущество декларативных языков, которое теряется, если вы копируете их с помощью процедурной программы ).
Кроме того, этот подход проблематичен, потому что обработка текста в циклах оболочки обычно считается плохой практикой .

Тем не менее, вот пример сценария оболочки, который использует стандартные утилиты, которые вы найдете предварительно -установленными на многих системах (, за исключением конструкции массива — не указанной в POSIX, но широко доступной,и, безусловно, доступен для вас, поскольку вы спрашиваете оbash):

#!/bin/bash

# The input file will be passed as the first argument
file="$1"

# For each input line:
# We take only the values of the first field, sort them, remove duplicates
for i in $(cut -d ',' -f 1 "$file" | sort -n -u); do

    # Resetting the array is not really needed; we do it for safety
    out=()

    # The first field of the output row is the key of the loop
    out[0]="$i"

    # We only consider the rows whose first field is equal
    # to the current key (grep) and...

    #... we sort the values of the second field
    # in ascending order and take only the first one
    out[1]="$(grep "^${out[0]}" "$file" | cut -d ',' -f 2 | sort -n | head -n 1)"

    #... we sort the values of the third field in
    # ascending order and take only the last one
    out[2]="$(grep "^${out[0]}" "$file" | cut -d ',' -f 3 | sort -n | tail -n 1)"

    #... we sort the values of the fourth field in
    # ascending order and take only the first one
    out[3]="$(grep "^${out[0]}" "$file" | cut -d ',' -f 4 | sort -n | head -n 1)"

    # Finally we print out the output, separating fields with ','
    printf '%s,%s,%s,%s\n' "${out[@]}"

done

Он должен вызываться как

./script file

Этот скрипт эквивалентен

SELECT col1, MIN(col2), MAX(col3), MIN(col4)
FROM text
GROUP BY col1
ORDER BY col1
0
28.01.2020, 05:06

Теги

Похожие вопросы