AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 282727
Accepted
vikrant rana
vikrant rana
Asked: 2021-01-08 02:24:56 +0800 CST2021-01-08 02:24:56 +0800 CST 2021-01-08 02:24:56 +0800 CST

Analisando dados JSON de uma coluna de texto no Postgres

  • 772

Eu tenho JSONem um arquivo da seguinte forma:

[xyz@innolx20122 ~]$ cat cgs_test.json
{"technology":"AAA","vendor":"XXX","name":"RBNI","temporal_unit":"hour","regional_unit":"cell","dataset_metadata":"{\"name\": \"RBNI\", \"temporal_unit\": \"hour\", \"technology\": \"LTE\", \"is_dimension\": false, \"timestamp_column_pattern\": \"yyyyMMddHHmmss\", \"data_type\": \"PM\", \"source_name\": \"RBNI\", \"intervals_epoch_seconds\": [[1609941600, 1609945200]], \"identifier_column_names\": [\"CELLID\", \"CELLNAME\", \"radio_frequency_band\", \"ENODEBID\", \"ENODEBNAME\", \"SBNID\", \"SITEID\", \"SITENAME\", \"CLUSTER_PRIORITY\", \"CP_SITE\", \"IBC\", \"NETWORK_TIER\", \"SITE_TYPE\", \"T3_FLAG\", \"CLUSTERID\", \"CLUSTERNAME\", \"REGION\", \"NETWORK\"], \"vendor\": \"ZTE\", \"timestamp_column_name\": \"COLLECTTIME\", \"regional_unit\": \"cell\"}","rk":1}
{"technology":"AAA","vendor":"XXX","name":"RRCADD","temporal_unit":"hour","regional_unit":"cell","dataset_metadata":"{\"name\": \"RRCADD\", \"temporal_unit\": \"hour\", \"technology\": \"AAA\", \"is_dimension\": false, \"timestamp_column_pattern\": \"yyyyMMddHHmmss\", \"data_type\": \"PM\", \"source_name\": \"RRCADD\", \"intervals_epoch_seconds\": [[1609941600, 1609945200]], \"identifier_column_names\": [\"CELLID\", \"CELLNAME\", \"radio_frequency_band\", \"ENODEBID\", \"ENODEBNAME\", \"SBNID\", \"SITEID\", \"SITENAME\", \"CLUSTER_PRIORITY\", \"CP_SITE\", \"IBC\", \"NETWORK_TIER\", \"SITE_TYPE\", \"T3_FLAG\", \"CLUSTERID\", \"CLUSTERNAME\", \"REGION\", \"NETWORK\"], \"vendor\": \"XXX\", \"timestamp_column_name\": \"COLLECTTIME\", \"regional_unit\": \"cell\"}","rk":1}

e eu carreguei isso para uma tabela temporária:

create table temp_json (values text);
\copy temp_json from '/home/xyz/cgs_test.json';

Agora eu quero extrair esses dados em colunas separadas como:

technology 
vendor
name
temporal_unit
regional_unit
dataset_metadata
rk

dataset_metadataé uma coluna JSON e outras colunas são strings.

postgresql
  • 2 2 respostas
  • 2727 Views

2 respostas

  • Voted
  1. Best Answer
    Vérace
    2021-01-08T05:16:32+08:002021-01-08T05:16:32+08:00

    Para responder a esta pergunta o que eu fiz foi o seguinte (veja violino aqui ):

    Esta foi uma experiência de aprendizado para mim (+1 para esse BTW), então vou seguir as etapas da minha lógica e espero que isso ajude você - mas estou fazendo isso por mim mesmo :-)

    Passo 1:

    CREATE TABLE temp_1 
    (
      json_input TEXT NOT NULL
    );
    

    Passo 2:

    Preencha-o com seus dois registros. No entanto, seus dois registros não são JSON apropriados - eles precisam de um [no início e ]no final para que sejam JSON apropriados - então, eu os coloquei INSERTno início do processo - deixo-o cabe ao leitor experimentar o que acontece se você os deixar de fora - você pode colocá-los mais tarde no processo - veja abaixo.

    Pode haver uma maneira de não ter que fazer isso com uma JSONfunção diferente - além da minha nota salarial, temo - mas gostaria de receber sugestões de melhorias.

    INSERT INTO temp_1 VALUES  -- strings copied from the question
    ('{"technology":"AAA","vendor":"XXX","name":"RBNI","temporal_unit":"hour","regional_unit":"cell","dataset_metadata":"{\"name\": \"RBNI\", \"temporal_unit\": \"hour\", \"technology\": \"LTE\", \"is_dimension\": false, \"timestamp_column_pattern\": \"yyyyMMddHHmmss\", \"data_type\": \"PM\", \"source_name\": \"RBNI\", \"intervals_epoch_seconds\": [[1609941600, 1609945200]], \"identifier_column_names\": [\"CELLID\", \"CELLNAME\", \"radio_frequency_band\", \"ENODEBID\", \"ENODEBNAME\", \"SBNID\", \"SITEID\", \"SITENAME\", \"CLUSTER_PRIORITY\", \"CP_SITE\", \"IBC\", \"NETWORK_TIER\", \"SITE_TYPE\", \"T3_FLAG\", \"CLUSTERID\", \"CLUSTERNAME\", \"REGION\", \"NETWORK\"], \"vendor\": \"ZTE\", \"timestamp_column_name\": \"COLLECTTIME\", \"regional_unit\": \"cell\"}","rk":1}'),
    ('{"technology":"AAA","vendor":"XXX","name":"RRCADD","temporal_unit":"hour","regional_unit":"cell","dataset_metadata":"{\"name\": \"RRCADD\", \"temporal_unit\": \"hour\", \"technology\": \"AAA\", \"is_dimension\": false, \"timestamp_column_pattern\": \"yyyyMMddHHmmss\", \"data_type\": \"PM\", \"source_name\": \"RRCADD\", \"intervals_epoch_seconds\": [[1609941600, 1609945200]], \"identifier_column_names\": [\"CELLID\", \"CELLNAME\", \"radio_frequency_band\", \"ENODEBID\", \"ENODEBNAME\", \"SBNID\", \"SITEID\", \"SITENAME\", \"CLUSTER_PRIORITY\", \"CP_SITE\", \"IBC\", \"NETWORK_TIER\", \"SITE_TYPE\", \"T3_FLAG\", \"CLUSTERID\", \"CLUSTERNAME\", \"REGION\", \"NETWORK\"], \"vendor\": \"XXX\", \"timestamp_column_name\": \"COLLECTTIME\", \"regional_unit\": \"cell\"}","rk":1}');
    

    Em seguida, transforme as strings em JSON da seguinte maneira - isso pode ser feito em massa:

    --
    --  This is to turn the "ordinary" strings into JSON per record. If this isn't
    --  done, the process will fail further down. Will work for an arbitrary number
    --  of records
    --
    
    UPDATE temp_1
    SET json_input = '[' || json_input || ']';
    

    Etapa 3:

    Crie outra tabela:

    CREATE TABLE temp_2
    (
      final_json JSON NOT NULL
    );
    

    Passo 4:

    Preencha isso por:

    INSERT INTO temp_2 SELECT json_input::JSON FROM temp_1; 
    

    O ::JSONcast é necessário, caso contrário o cast INSERTirá falhar como json_inputé do tipo TEXT.

    Em seguida, limpe `temp_1':

    --
    --  Clear down temp_1.
    --  This is needed for next batch, otherwise you'll have strings beginning 
    --  with '[[' and then '[[[' (endings same with multiple ']'s) and so on!
    --
    
    DELETE FROM temp_1;
    

    Etapa 5:

    Crie uma tabela para armazenar os dados:

    CREATE TABLE json_table
    (
      technology TEXT,
      vendor TEXT,
      name TEXT,
      temporal_unit TEXT,
      regional_unit TEXT,
      dataset_metadata JSON,
      rk SMALLINT
    );
    

    Etapa 6:

    A partir daqui , obtive este método para preencher a tabela:

    INSERT INTO json_table 
    SELECT (json_populate_recordset(null::json_table, final_json)).* FROM temp_2;
    

    Há outra maneira mostrada no violino - daqui - YMMV?

    Passo 7 - verificação final:

    SELECT * FROM json_table;
    

    Resultado:

    technology  vendor  name    temporal_unit   regional_unit   dataset_metadata    rk
    AAA XXX RBNI    hour    cell    "{\"name\": \"RBNI\", \"temporal_unit\": \"hour\", \"technology\": \"LTE\", \"is_dimension\": false, \"timestamp_column_pattern\": \"yyyyMMddHHmmss\", \"data_type\": \"PM\", \"source_name\": \"RBNI\", \"intervals_epoch_seconds\": [[1609941600, 1609945200]], \"identifier_column_names\": [\"CELLID\", \"CELLNAME\", \"radio_frequency_band\", \"ENODEBID\", \"ENODEBNAME\", \"SBNID\", \"SITEID\", \"SITENAME\", \"CLUSTER_PRIORITY\", \"CP_SITE\", \"IBC\", \"NETWORK_TIER\", \"SITE_TYPE\", \"T3_FLAG\", \"CLUSTERID\", \"CLUSTERNAME\", \"REGION\", \"NETWORK\"], \"vendor\": \"ZTE\", \"timestamp_column_name\": \"COLLECTTIME\", \"regional_unit\": \"cell\"}"   1
    AAA XXX RRCADD  hour    cell    "{\"name\": \"RRCADD\", \"temporal_unit\": \"hour\", \"technology\": \"AAA\", \"is_dimension\": false, \"timestamp_column_pattern\": \"yyyyMMddHHmmss\", \"data_type\": \"PM\", \"source_name\": \"RRCADD\", \"intervals_epoch_seconds\": [[1609941600, 1609945200]], \"identifier_column_names\": [\"CELLID\", \"CELLNAME\", \"radio_frequency_band\", \"ENODEBID\", \"ENODEBNAME\", \"SBNID\", \"SITEID\", \"SITENAME\", \"CLUSTER_PRIORITY\", \"CP_SITE\", \"IBC\", \"NETWORK_TIER\", \"SITE_TYPE\", \"T3_FLAG\", \"CLUSTERID\", \"CLUSTERNAME\", \"REGION\", \"NETWORK\"], \"vendor\": \"XXX\", \"timestamp_column_name\": \"COLLECTTIME\", \"regional_unit\": \"cell\"}"   1
    

    Um par de pensamentos:

    • Seu dataset_metadatacampo não parece ser um JSON "adequado" - talvez um adequado REGEXP_REPLACEe/ou um CASTpossa estar em ordem? Não conheço o processo pelo qual você obtém seu /home/xyz/cgs_test.jsonarquivo - mas pode valer a pena observar como o registro é gerado - idealmente, você deve corrigir quaisquer problemas o mais cedo possível no pipeline.

    • Eu não sei suas circunstâncias exatas, mas você deve considerar cuidadosamente o conselho aqui - você pode querer agrupar seus metadados em uma tabela separada com uma FOREIGN KEYconexão com o registro pai?

    • 5
  2. Melkij
    2021-01-08T05:44:26+08:002021-01-08T05:44:26+08:00

    COPY não se destina a preencher cada linha na coluna como está. Ele quebrará alguma formatação de linha na codificação json aninhada.

    Em vez de COPY, você pode usar pg_read_filea função admin para ler o arquivo e depois dividir este texto por linha:

    create temp table temp_json as
    select v::json 
     from regexp_split_to_table(
         trim(pg_read_file('/tmp/json'), E'\n'), 
     '[\n\r]+') as v;
    

    Então, vemos que o JSON está correto. Vamos reformatar conforme necessário:

    select v->>'technology', 
    v->>'vendor', 
    v->>'name', 
    v->>'temporal_unit', 
    v->>'regional_unit', 
    v->>'dataset_metadata', 
    v->>'rk' 
    from temp_json ;
    
    -[ RECORD 1 ]--
    ?column? | AAA
    ?column? | XXX
    ?column? | RBNI
    ?column? | hour
    ?column? | cell
    ?column? | {"name": "RBNI", "temporal_unit": "hour", "technology": "LTE", "is_dimension": false, "timestamp_column_pattern": "yyyyMMddHHmmss", "data_type": "PM", "source_name": "RBNI", "intervals_epoch_seconds": [[1609941600, 1609945200]], "identifier_column_names": ["CELLID", "CELLNAME", "radio_frequency_band", "ENODEBID", "ENODEBNAME", "SBNID", "SITEID", "SITENAME", "CLUSTER_PRIORITY", "CP_SITE", "IBC", "NETWORK_TIER", "SITE_TYPE", "T3_FLAG", "CLUSTERID", "CLUSTERNAME", "REGION", "NETWORK"], "vendor": "ZTE", "timestamp_column_name": "COLLECTTIME", "regional_unit": "cell"}
    ?column? | 1
    -[ RECORD 2 ]-
    ?column? | AAA
    ?column? | XXX
    ?column? | RRCADD
    ?column? | hour
    ?column? | cell
    ?column? | {"name": "RRCADD", "temporal_unit": "hour", "technology": "AAA", "is_dimension": false, "timestamp_column_pattern": "yyyyMMddHHmmss", "data_type": "PM", "source_name": "RRCADD", "intervals_epoch_seconds": [[1609941600, 1609945200]], "identifier_column_names": ["CELLID", "CELLNAME", "radio_frequency_band", "ENODEBID", "ENODEBNAME", "SBNID", "SITEID", "SITENAME", "CLUSTER_PRIORITY", "CP_SITE", "IBC", "NETWORK_TIER", "SITE_TYPE", "T3_FLAG", "CLUSTERID", "CLUSTERNAME", "REGION", "NETWORK"], "vendor": "XXX", "timestamp_column_name": "COLLECTTIME", "regional_unit": "cell"}
    ?column? | 1
    

    Você também pode converter JSON aninhado em dataset_metadata para o tipo de dados JSON e processá-lo ainda mais como desejar. Por exemplo,

    select v->>'name', 
      cast((v->>'dataset_metadata') as json)->'vendor' as meta_vendor
      from temp_json ;
    -[ RECORD 1 ]-------
    ?column?    | RBNI
    meta_vendor | "ZTE"
    -[ RECORD 2 ]-------
    ?column?    | RRCADD
    meta_vendor | "XXX"
    
    • 4

relate perguntas

  • Posso ativar o PITR depois que o banco de dados foi usado

  • Práticas recomendadas para executar a replicação atrasada do deslocamento de tempo

  • Os procedimentos armazenados impedem a injeção de SQL?

  • Sequências Biológicas do UniProt no PostgreSQL

  • Qual é a diferença entre a replicação do PostgreSQL 9.0 e o Slony-I?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve