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 / 340510
Accepted
Luke Hutchison
Luke Hutchison
Asked: 2024-06-26 05:01:51 +0800 CST2024-06-26 05:01:51 +0800 CST 2024-06-26 05:01:51 +0800 CST

Escopo do alias de coluna no Postgres?

  • 772

Tenho a seguinte estrutura de tabela em meu banco de dados Postgres: tabela chat_channelpossui uma coluna otherUserIdque pode ser unida com tabela a coluna userIdde outra tabela, profile. A tabela profilepossui colunas userIdque podem ser unidas à coluna senderUserIdou recipientUserIdna tabela note.

Para qualquer linha que chat_channelcorresponda a determinados critérios de consulta, desejo extrair a única linha de profileonde chat_channel."otherUserId" = profile."userId"(como colunas extras retornadas da consulta). Também quero extrair colunas da linha correspondente notepara cada uma das duas userIdcorrespondências possíveis: where profile."userId" = note."senderUserId"e where profile."userId" = note."recipientUserId".

Estou tendo problemas para descobrir como criar um alias adequado de colunas para essa consulta duplamente aninhada, visto que a consulta interna ingressa na mesma tabela duas vezes.

Tenho que criar um alias para as colunas, pois estou retornando colunas da mesma tabela duas vezes nas linhas de resultados. Além disso, as tabelas compartilham colunas com o mesmo nome (principalmente id).

Tentativa (1):

SELECT    "chat_channel"."id" "chat_channel.id",
          "chat_channel"."channelId" "chat_channel.channelId",
          "chat_channel"."userId" "chat_channel.userId",
          "chat_channel"."otherUserId" "chat_channel.otherUserId",
          "chat_channel"."sortByDateTime" "chat_channel.sortByDateTime",
          "profile_other_user"."userId" "profile_other_user.userId",
          "profile_other_user"."name" "profile_other_user.name",
          "note_viewer_sent"."id" "note_viewer_sent.id",  -- (a)
          "note_viewer_sent"."senderUserId" "note_viewer_sent.senderUserId",
          "note_viewer_sent"."recipientUserId" "note_viewer_sent.recipientUserId",
          "note_viewer_sent"."noteText" "note_viewer_sent.noteText",
          "note_viewer_received"."id" "note_viewer_received.id",
          "note_viewer_received"."senderUserId" "note_viewer_received.senderUserId",
          "note_viewer_received"."recipientUserId" "note_viewer_received.recipientUserId",
          "note_viewer_received"."noteText" "note_viewer_received.noteText"
FROM      "chat_channel"
LEFT JOIN LATERAL (
    SELECT    "profile_other_user"."id",
              "profile_other_user"."userId",
              "profile_other_user"."name"
    FROM      "profile" "profile_other_user"
    LEFT JOIN LATERAL (
        SELECT "note_viewer_sent"."id",
               "note_viewer_sent"."senderUserId",
               "note_viewer_sent"."recipientUserId",
               "note_viewer_sent"."noteText"
        FROM   "note" "note_viewer_sent"  -- (b)
        WHERE  "note_viewer_sent"."recipientUserId" = "profile_other_user"."userId"
                AND "note_viewer_sent"."senderUserId" = $viewerUserId
        LIMIT 1
    ) AS "note_viewer_sent" ON TRUE  -- (c)
    LEFT JOIN LATERAL (
        SELECT "note_viewer_received"."id",
               "note_viewer_received"."senderUserId",
               "note_viewer_received"."recipientUserId",
               "note_viewer_received"."noteText"
        FROM   "note" "note_viewer_received"
        WHERE  "note_viewer_received"."senderUserId" = "profile_other_user"."userId"
                AND "note_viewer_received"."recipientUserId" = $viewerUserId
        LIMIT 1
    ) AS "note_viewer_received" ON TRUE
    WHERE "chat_channel"."otherUserId" = "profile_other_user"."userId"
    LIMIT 1
) AS "profile_other_user" ON TRUE
WHERE "chat_channel"."userId" = $viewerUserId
ORDER BY  "chat_channel"."sortByDateTime" DESC

Problemas com isso:

  • Isso dá ERROR: missing FROM-clause entry for table "note_viewer_sent"na linha marcada -- (a).
  • Tentar criar um alias para a tabela ( -- (b)) não resolve o problema.
  • Tentar criar um alias para os resultados da consulta mais profunda ( -- (c)) não resolve o problema.

Tentativa (2):

No entanto, se eu fizer a FROMcláusula de nível superior

FROM      "chat_channel", "note" "note_viewer_sent", "note" "note_viewer_received"

então o erro não é mais gerado, mas as WHEREcláusulas mais internas parecem ser ignoradas:

WHERE  "note_viewer_sent"."recipientUserId" = "profile_other_user"."userId"
       AND "note_viewer_sent"."senderUserId" = $viewerUserId

Especificamente, cada linha do conjunto de resultados contém colunas da mesma linha (errada) de notes, para a qual a WHEREcondição nem sequer é válida.

Além disso, parece que o efeito padrão de colocar várias tabelas FROMé obter um produto cruzado das tabelas. (Não posso reproduzir isso agora, mas a certa altura eu estava recebendo uma cópia de cada linha de profilepara cada linha de chat_channele as LIMIT 1consultas internas estavam sendo ignoradas.)

Alguma idéia sobre o que estou fazendo de errado aqui?

postgresql
  • 1 1 respostas
  • 32 Views

1 respostas

  • Voted
  1. Best Answer
    Erwin Brandstetter
    2024-06-26T06:03:31+08:002024-06-26T06:03:31+08:00

    A causa imediata da mensagem de erro é que você não pode fazer referência a nomes de colunas de saída de subconsultas aninhadas na SELECTlista externa. Poderia ser corrigido como:

    SELECT    "chat_channel"."id" "chat_channel.id",
           -- ...
    FROM      "chat_channel"
    LEFT JOIN LATERAL (
        SELECT *  -- !!!
        FROM   "profile" "profile_other_user"
        ...
        ) AS "profile_other_user" ON TRUE
    

    Ou melhor:

    SELECT c.id AS chat_channel_id,
        -- ...
           p.name AS profile_other_user_name,
           p.note_viewer_sent_id,      -- !
        -- ... 
           p.note_viewer_received_id,  -- !
        -- ...
    FROM   chat_channel c
    LEFT   JOIN LATERAL (
       SELECT *  -- !!!
       FROM   profile p
       LEFT   JOIN LATERAL (
          SELECT n.id AS note_viewer_sent_id  -- distinct alias
              -- ...
          FROM   note n
          WHERE  n."recipientUserId" = p."userId"  -- are you sure you ...
          AND    ...
          ) ns ON true
       LEFT   JOIN LATERAL (
          SELECT n.id AS note_viewer_received_id  -- distinct alias
              -- ...
          FROM   note n
          WHERE  n."senderUserId" = p."userId"  -- ... did not confuse sender/receiver here?!
          AND    ...
       -- ORDER  BY ???
          LIMIT  1
          ) nk ON true
       WHERE  p."userId" = c."otherUserId"
    -- ORDER  BY ???
       LIMIT  1
       ) p ON true
    -- ...
    

    Isso passa por todas as colunas da FROMlista da subconsulta. Você deve distribuir aliases de coluna exclusivos nas subconsultas aninhadas, é claro, e referenciar o alias da tabela pna SELECTlista externa.

    Há uma lista de outros problemas aqui ...

    • Use exclusivamente identificadores legais, em letras minúsculas e sem aspas, para que você não precise usar aspas duplas. Ver:

      • Os nomes das colunas do PostgreSQL diferenciam maiúsculas de minúsculas?
    • Em particular, nunca inclua pontos nos identificadores entre aspas. Isso é realmente tentar tornar sua vida difícil.

    • Não omita a ASpalavra-chave para aliases de coluna.
      Mas não há problema em omitir a ASpalavra-chave para aliases de tabela.
      Você entende o contrário. Relacionado:

      • Aliases com subconsultas correlacionadas
    • LIMITsem determinístico ORDER BYretorna linhas arbitrárias. Não está claro se você deseja isso ou se precisa mesmo LIMITpara começar.

    • Pelo menos um nível LATERALé supérfluo.

    • Se a coluna puder ser nula, você provavelmente NULLS LASTdesejará

      ORDER BY "chat_channel"."sortByDateTime" DESC NULLS LAST
      

      Ver:

      • Classificar por coluna ASC, mas valores NULL primeiro?

    O problema com nomes de colunas duplicados é agravado pelo antipadrão generalizado de usar "id" como nome de coluna em todas as tabelas. Não desaconselho, mas essa é apenas a minha opinião, ao contrário dos itens acima, que não são uma questão de opinião - na minha opinião. :) Mais sobre isso:

    • Como implementar um relacionamento muitos para muitos no PostgreSQL?
    • 3

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