Pergunta

Estou executando o Access 2003. Estou usando o Switch para selecionar campos de data com base em um critério booleano:

Switch(<criterion>, Date1, 1, Date2)

isto é, se "critério" for verdadeiro, retornar a data1, caso contrário, retorne a data2.

Date1 e Date2 são colunas de data/hora em uma tabela.

O problema é que o Switch os retorna como texto - não data/hora!

Existe uma maneira de forçá-los a ser encontrados? eu tentei

Switch(<criterion>, #Date1#, 1, #Date2#)

E

Switch(<criterion>, Val(Date1), 1, Val(Date2))

Ambos falham com uma mensagem de erro ou outra.

Alguma ideia?

Foi útil?

Solução

Eu acho que a função imediata se [iif ()] é uma correspondência melhor para o que você está tentando fazer:

IIf(<criterion>, Date1, Date2)

Mas a função Switch () não deve quebrar os tipos de dados e não é incompatível com os tipos de dados de data/hora. Considere esta função:

Public Function trySwitch(ByVal pWhichDay As String) As Variant
    Dim varOut As Variant
    varOut = Switch(pWhichDay = "yesterday", Date - 1, _
        pWhichDay = "today", Date, _
        pWhichDay = "tomorrow", Date + 1)
    trySwitch = varOut
End Function

Tryswitch ("Today") retorna 10/6/2009 e Typename (Tryswitch ("Today")) retorna Encontro

Outras dicas

Há algo estranho com o seu exemplo.

O Switch aceita pares de expressão e, se o primeiro avaliar como verdadeiro, seu valor emparelhado será retornado, caso contrário, ele passa para o segundo e avalia esse argumento.

Você parece estar tratando 1 como verdadeiro, o que é porque não é Fales, mas você estaria melhor com:

  Switch(<criterion>, Date1, True, Date2)

Mas isso é apenas uma replicação da funcionalidade da função imediata, iif () e iif (), leva menos argumentos.

Mas tem o mesmo problema, na medida em que retorna uma variante. Mas você deve ser capaz de coagir isso para um tipo de dados que pode ser formatado como uma data.

Mas se essa variante será implicitamente coagida ou você precisará fazê -lo explicitamente, depende de onde você está usando. Em um resultado de consulta, você pode classificar a saída do IIF ([Critério], Date1, Date2) como uma data, porque a coluna é coagida até o tipo de data.

Se você precisar fazer a coerção explicitamente, o CDATE () é a função de usar - você envolve a função externa que produz saída variante com a função cdate () para ter certeza de que a saída variante é explicitamente coagida até o momento modelo:

  CDate(IIf(<criterion>, Date1, Date2))

Mas posso muito bem estar perdendo algo importante aqui, pois pareço estar em uma faixa completamente diferente ...

Você pode postar algum código e dados para reproduzir o problema, por favor? Como isso é SWITCH() No código SQL, então eu acho que o SQL DDL (CREATE TABLE etc) e DML (INSERT INTO para adicionar dados) seria mais apropriado :)

PICKY PONTO: O ACCESS DATABASE SQL não possui um tipo de dados 'booleano'. Tem um YESNO tipo de dados que pode ser o NULL valor; A lógica de três valores não é booleana.

Aqui estão alguns SQL DML (Modo de consulta ANSI-92 sintaxe) para demonstrar como funciona como esperado para mim:

SELECT TYPENAME
       (
          SWITCH
          (
             NULL, #2009-01-01 00:00:00#, 
             FALSE, #2009-06-15 12:00:00#, 
             TRUE, #2009-12-31 23:59:59#
          )
       );

Altere qualquer um dos valores do 'critério' e o valor é sempre retornado como 'data', ou seja, do tipo DATETIME.


ATUALIZAR:

Este TYPENAME A função é uma ótima ferramenta ... o acesso parece interpretar toda a "coluna" do resultado do resultado de maneira diferente

De fato. Porque uma coluna pode ser apenas um tipo de dados os resultados de TYPENAME() Na fila pode ser enganosa. Os valores de linha dos tipos mistos devem ser 'promovidos' para um tipo de dados mais alto. Como é habitual com o mecanismo de banco de dados de acesso, o processo é totalmente opaco e a documentação sobre o assunto completamente ausente, então você só precisa sugar e ver por exemplo

SELECT #2009-01-01 00:00:00# AS row_value, 
       TYPENAME(#2009-01-01 00:00:00#) AS row_type
  FROM Customers
UNION ALL
SELECT 0.5, 
       TYPENAME(0.5) AS row_type
  FROM Customers

Retornos 'data' e 'decimal', respectivamente, mas qual será a coluna? Aparentemente, a resposta é:

SELECT DT1.row_value, TYPENAME(DT1.row_value) AS column_type
  FROM (
        SELECT DISTINCT #2009-01-01 00:00:00# AS row_value 
          FROM Customers
        UNION ALL
        SELECT DISTINCT 0.5
          FROM Customers
       ) AS DT1;

'Corda'?!

... O que, obviamente, nem nem é um tipo de dados SQL de mecanismo de banco de dados de acesso. Então TYPENAME(), irritantemente, usa o nome do tipo 'melhor ajuste' VBA. Por exemplo:

SELECT TYPENAME(CBOOL(0));

Retorna 'Boolean', embora, como discutido acima, não existe um tipo de dados booleano no SQL do mecanismo de banco de dados de acesso. E

SELECT TYPENAME(my_binary_col)

retorna 'string'. Observe a mesma limitação de mapeamento VBA se aplica ao CAST funções (ainda outro aborrecimento), por exemplo, não há 'elenco para BINARY'função e o CDEC() A função permanece quebrada desde o jet 4.0 :(

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top