Невозможно перебрать массив в bash для экспорта запросов PostgreSQL - PullRequest
0 голосов
/ 19 мая 2018

У меня есть запрос PostgreSQL, который я хотел бы выполнить для нескольких географических областей через цикл.Я хочу использовать элементы в массиве, чтобы изменить запрос и имя файла CSV, в который я экспортирую данные.По сути, я хочу, чтобы запрос выполнялся на ... cwa = 'MFR' ... и экспортировался в hourly_MFR.csv, затем выполнялся на ... cwa = 'PQR' ... и экспортировался в hourly_PQR.csv,и так далее.

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

Кроме того, запрос / скрипт без циклов (исключая операторы объявления, выполнения, выполнения) работает нормально.

dbname="XXX"

username="XXXXX"

psql $dbname $username << EOF

declare -a arr=('MFR', 'PQR', 'REV')

for i in "${arr[@]}"

do

\COPY
(SELECT d.woyhh,
      COALESCE(ct.ct, 0) AS total_count
FROM
 (SELECT f_woyhh(d::TIMESTAMP) AS woyhh
  FROM generate_series(TIMESTAMP '2018-01-01', TIMESTAMP '2018-12-31', interval '1 hour') d) d
LEFT JOIN
 (SELECT f_woyhh((TIME)::TIMESTAMP) AS woyhh,
         count(*) AS ct
  FROM counties c
  JOIN ltg_data d ON ST_contains(c.the_geom, d.ltg_geom)
  WHERE cwa = $i
  GROUP BY 1) ct USING (whh)
ORDER BY 1) TO /var/www/html/GIS/ltg_db/bigquery/hourly_$i.csv CSV HEADER;

done

EOF

Спасибо за любую помощь!

Ответы [ 2 ]

0 голосов
/ 19 мая 2018

В ответе @ Lienhart Woitok выше решение определенно сработает.Однако обратите внимание, что это имеет побочный эффект от выполнения нового вызова psql, настройки соединения с базой данных, аутентификации и последующего возврата ответа;с последующим закрытием соединения - для каждой итерации цикла.

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

Для этого может потребоваться использование временного рабочего файла для построения команд SQL.Есть и другие способы, но это относительно просто для использования и отладки:

QUERY_FILE=$(mktemp /tmp/query.XXXXXXX)

# note the use of an array isn't really necessary in this use
# case - and a simple set of values can be used equally as well
CWA="MFR PQR REV"

for i in $CWA
do
 cat <<EOF >> $QUERY_FILE
     <ADD_YOUR_QUERY_STATEMENTS_HERE>
EOF
done

psql --file=$QUERY_FILE $dbname $username

if (( $? )) 
then
  echo "query failed (QUERY_FILE: ($QUERY_FILE')"
  exit 1 
else
  echo "query succeeded"
  rm -f $QUERY_FILE
  exit 0
fi
0 голосов
/ 19 мая 2018

Я думаю, что вы почти у цели, вам просто нужно изменить порядок строк.Попробуйте это:

dbname="XXX"

username="XXXXX"

declare -a arr=('MFR', 'PQR', 'REV')

for i in "${arr[@]}"
do

psql $dbname $username << EOF

\COPY
(SELECT d.woyhh,
      COALESCE(ct.ct, 0) AS total_count
FROM
 (SELECT f_woyhh(d::TIMESTAMP) AS woyhh
  FROM generate_series(TIMESTAMP '2018-01-01', TIMESTAMP '2018-12-31', interval '1 hour') d) d
LEFT JOIN
 (SELECT f_woyhh((TIME)::TIMESTAMP) AS woyhh,
         count(*) AS ct
  FROM counties c
  JOIN ltg_data d ON ST_contains(c.the_geom, d.ltg_geom)
  WHERE cwa = $i
  GROUP BY 1) ct USING (whh)
ORDER BY 1) TO /var/www/html/GIS/ltg_db/bigquery/hourly_$i.csv CSV HEADER;

EOF

done

Цикл declare и for являются частью скрипта bash, в то время как все между <<EOF и EOF являются частью вашего запроса Postgresql.

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