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 / 77266
Accepted
lumo
lumo
Asked: 2014-09-23 04:51:46 +0800 CST2014-09-23 04:51:46 +0800 CST 2014-09-23 04:51:46 +0800 CST

Alternativas para uma consulta LEFT OUTER JOIN

  • 772

Problema

Eu tenho uma instrução SQL com um LEFT OUTER JOINque funciona bem em nosso arquivo Microsoft SQL Server. Meu problema é que tenho que ser compatível H2 Databasee este tem um bug com OUTER JOINS.


Consulta SQL

SELECT *
FROM tSysNls
WHERE nlsGuid IN
    ( SELECT nlsGuid = CASE 
    WHEN de_AT.nlsGuid IS NOT NULL THEN de_AT.nlsGuid 
    WHEN de.nlsGuid IS NOT NULL THEN de.nlsGuid ELSE en.nlsGuid 
    END
    FROM tSysNLS en
    LEFT OUTER JOIN tSysNLS de ON en.nlsAttribute=de.nlsAttribute
        AND en.nlsClazz=de.nlsClazz
        AND de.nlsLocale= 'de'
    LEFT OUTER JOIN tSysNLS de_AT ON de.nlsAttribute=de_AT.nlsAttribute
        AND de.nlsClazz=de_AT.nlsClazz
        AND de_AT.nlsLocale= 'de_AT'
    WHERE en.nlsLocale= 'en'
        AND en.nlsClazz= 'Contact'
        AND en.nlsAttribute= 'firstName')

Mesa

CREATE TABLE tsysNLS
(
   nlsGuid           nvarchar(207)   NOT NULL,
   nlsLocale         nvarchar(5)     NOT NULL,
   nlsClazz          nvarchar(100)   NOT NULL,
   nlsAttribute      nvarchar(100)   NOT NULL,
   nlsDisplayName    nvarchar(255)   NOT NULL,
   nlsOldname        nvarchar(50),
   nlsDescription    nvarchar(255),
   nlsShapefilename  nvarchar(10)
);

dados de exemplo

INSERT INTO tsysNLS(nlsGuid, nlsLocale, nlsClazz, nlsAttribute, nlsDisplayName, nlsOldname, nlsDescription, nlsShapefilename)
VALUES(N'Contact.firstName.en', N'en', N'Contact', N'firstName', N'Name - First Name', N'conFirstName', N'Name - First Name', NULL);
INSERT INTO tsysNLS(nlsGuid, nlsLocale, nlsClazz, nlsAttribute, nlsDisplayName, nlsOldname, nlsDescription, nlsShapefilename)
VALUES(N'Contact.firstName.de', N'de', N'Contact', N'firstName', N'Vorname', N'conFirstName', NULL, N'ConNamVor');
INSERT INTO tsysNLS(nlsGuid, nlsLocale, nlsClazz, nlsAttribute, nlsDisplayName, nlsOldname, nlsDescription, nlsShapefilename)
VALUES(N'Contact.firstName.de_AT', N'de_AT', N'Contact', N'firstName', N'Vorname (AT)', N'conFirstName', NULL, N'ConNamVor');
sql-server join
  • 3 3 respostas
  • 12808 Views

3 respostas

  • Voted
  1. Daniel Hutmacher
    2014-09-23T05:30:03+08:002014-09-23T05:30:03+08:00

    Você pode reescrever o LEFT JOINpara uma subconsulta, mas ainda pode compilar como uma consulta de junção externa - não tenho conhecimento desses aspectos da plataforma H2.

    SELECT *
    FROM tSysNls
    WHERE nlsGuid IN (
        SELECT COALESCE(
               --- first option:
               (SELECT de_AT.nlsGuid
                FROM tSysNLS AS de_AT
                WHERE de_AT.nlsClazz=x.nlsClazz AND
                      de_AT.nlsAttribute=en.nlsAttribute AND
                      de_AT.nlsLocale='de_AT'),
               --- second option:
               (SELECT de.nlsGuid
                FROM tSysNLS AS de
                WHERE de.nlsClazz=x.nlsClazz AND
                      de.nlsAttribute=en.nlsAttribute AND
                      de.nlsLocale='de'),
               --- third option:
               en.nlsGuid)
        FROM tSysNLS AS en
        WHERE en.nlsLocale='en'
            AND en.nlsClazz='Contact'
            AND en.nlsAttribute='firstName');
    

    Ou você pode criar algum tipo de tabela temporária (ou uma tabela regular se o H2 não suportar tabelas temporárias) e preenchê-la em três etapas. Novamente, isso provavelmente ainda será compilado usando um anti-semijoin ou algum outro tipo de junção externa, mas talvez funcione como uma solução alternativa para o seu bug:

    --- 1. de_AT, if there are any:
    INSERT INTO #temptable SELECT * FROM tSysNls
    WHERE nlsLocale='de_AT' AND nlsClazz='Contact' AND nlsAttribute='firstName';
    
    --- 2. de for those that don't have de_AT:
    INSERT INTO #temptable SELECT * FROM tSysNls
    WHERE nlsLocale='de' AND nlsClazz='Contact' AND nlsAttribute='firstName'
          AND nlsGuid NOT IN (SELECT nlsGuid FROM #temptable);
    
    --- 3. en for the remaining records:
    INSERT INTO #temptable SELECT * FROM tSysNls
    WHERE nlsLocale='en' AND nlsClazz='Contact' AND nlsAttribute='firstName'
          AND nlsGuid NOT IN (SELECT nlsGuid FROM #temptable);
    
    SELECT * FROM #temptable;
    

    Mas essas não são soluções bonitas.

    • 3
  2. Best Answer
    lumo
    2014-09-26T21:33:51+08:002014-09-26T21:33:51+08:00

    Solução

    isso não é exatamente o que eu pedi, mas resolve o problema da consulta original falhar, H2 Database obrigado ypercube, sua sugestão está correta

    SELECT *
    FROM tSysNls
    WHERE nlsGuid IN
        ( SELECT CASE 
        WHEN de_AT.nlsGuid IS NOT NULL THEN de_AT.nlsGuid 
        WHEN de.nlsGuid IS NOT NULL THEN de.nlsGuid ELSE en.nlsGuid 
        END AS nlsGuid
        FROM tSysNLS en
        LEFT OUTER JOIN tSysNLS de ON en.nlsAttribute=de.nlsAttribute
            AND en.nlsClazz=de.nlsClazz
            AND de.nlsLocale= 'de'
        LEFT OUTER JOIN tSysNLS de_AT ON de.nlsAttribute=de_AT.nlsAttribute
            AND de.nlsClazz=de_AT.nlsClazz
            AND de_AT.nlsLocale= 'de_AT'
        WHERE en.nlsLocale= 'en'
            AND en.nlsClazz= 'Contact'
            AND en.nlsAttribute= 'firstName')
    

    resulta em um resultado correto.

    mas devido ao (muito) melhor desempenho eu processo toda a tabela para objetos em meu aplicativo agora e pego os objetos (selecione qual é o correto por código)

    • 1
  3. lumo
    2014-09-23T21:37:50+08:002014-09-23T21:37:50+08:00

    eu tive duas consultas sem junção externa, que funcionaram rápido e corretas, Microsoft SQL Servermas ambas não funcionaram em H2 Database uma delas porque MSSQLusa + para concatenar strings e H2usa CONCAT (que é uma porcaria porque afaik isso não corresponde às especificações SQL)

    minha solução final é criar uma única consulta em meu código e encontrar o material correto com o código.


    Uma das consultas que tentei foi esta (funciona, Microsoft SQL Servermas não em H2 devido à sintaxe concatenada diferente)


    SELECT * FROM tSysNLS
    WHERE nlsGuid = CASE
    WHEN exists(select * from tSysNLS where nlsClazz = ?4 and nlsAttribute = ?5 and nlsLocale = ?2) then ?4+'.'+?5+'.'+?2
    WHEN exists(select * from tSysNLS where nlsClazz = ?4 and nlsAttribute = ?5 and nlsLocale = ?1) then ?4+'.'+?5+'.'+?1
    ELSE ?4+'.'+?5+'.'+?3
    END
    

    onde ?# são os parâmetros
    ?1 = 'de_AT'
    ?2 = 'de'
    ?3 = 'en'
    ?4 = 'Contato'
    ?5 = 'primeiroNome'

    • -4

relate perguntas

  • Qual é a diferença entre um INNER JOIN e um OUTER JOIN?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como é a saída de uma instrução JOIN?

  • Como determinar se um Índice é necessário ou necessário

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