2010-03-07 19 views
37

Ho una tabella con le seguenti colonne: EntityID, entityName, EntityProfile, .................Come selezionare vero/falso in base al valore della colonna?

Voglio selezionare l'ID e il nome e vero/false column in base al valore del profilo dell'entità, ad esempio un set di risultati restituito come di seguito, significherebbe che le entità 1 & 2 hanno profili mentre 3 non.

1 Name1 True 
2 Name2 True 
3 Name3 False 
etc..... 

so che posso farlo utilizzando una funzione che restituiscono vero/falso sulla base del valore del profilo in questo modo: SELEZIONA EntityID, EntityName, dbo.EntityHasProfile (EntityID) AS HasProfile dalle entità

ma Sto tornando un grande no. di record e con questa chiamata di funzione per ogni record, la query è molto lenta e quando rimuovo la chiamata di funzione il tempo di esecuzione della query diminuisce in modo significativo.

Quindi c'è un altro modo per farlo? Grazie

+2

Probabilmente "unisci", ma non ci hai detto come viene calcolato "EntityHasProfile'. Hai un altro tavolo? – Kobi

+0

scusate ho dimenticato di dirlo, il profilo dell'entità è nvarchar (max) – Yasmine

+0

E come si usa EntityProfile per determinare se EntityHasProfile? Se è nulla ...? – froadie

risposta

73

Utilizzare un CASE. Vorrei pubblicare il codice specifico, ma ho bisogno di più informazioni di quelle fornite nel post, come il tipo di dati di EntityProfile e ciò che di solito è memorizzato in esso. Qualcosa di simile:

CASE WHEN EntityProfile IS NULL THEN 'False' ELSE 'True' END 

Modifica - l'intera istruzione SELECT, come da informazioni nei commenti:

SELECT EntityID, EntityName, 
     CASE WHEN EntityProfile IS NULL THEN 'False' ELSE 'True' END AS HasProfile 
FROM Entity 

No LEFT JOIN necessario in questo caso ...

+0

Cosa succede se ho un 20 e sopra le colonne che ha un bit (vero/falso) tipo di dati? Lo stesso può essere applicato @froadie – Kopika

+2

Per espandere questa risposta, questo restituisce una puntura di Vero o Falso. Soddisfa completamente l'OP ma può essere più utile come un campo T/F bit reale (come menzionato da Kopika). Userei questo caso dichiarazione: SELEZIONA EntityID, EntityName, cast (CASO QUANDO EntityProfile IS NULL ALLORA 0 ELSE 1 END) come bit) AS HasProfile dall'entità – Rob

+0

@ Rob Grazie per questo. ma una parentesi aperta una volta, chiusa due volte? – Jasir

6

Si può provare qualcosa di simile

SELECT e.EntityId, 
     e.EntityName, 
     CASE 
      WHEN ep.EntityId IS NULL THEN 'False' 
      ELSE 'TRUE' 
     END AS HasProfile 
FROM Entities e LEFT JOIN 
     EntityProfiles ep ON e.EntityID = ep.EntityID 

O

SELECT e.EntityId, 
     e.EntityName, 
     CASE 
      WHEN e.EntityProfile IS NULL THEN 'False' 
      ELSE 'TRUE' 
     END AS HasProfile 

FROM Entities e 
0

Che cosa significa l'UDF EntityHasProfile() fare?

In genere si potrebbe fare qualcosa di simile con un LEFT JOIN:

SELECT EntityId, EntityName, CASE WHEN EntityProfileIs IS NULL THEN 0 ELSE 1 END AS Has Profile 
FROM Entities 
LEFT JOIN EntityProfiles 
    ON EntityProfiles.EntityId = Entities.EntityId 

Questo dovrebbe eliminare la necessità di una chiamata scalari UDF costosi - nella mia esperienza, UDF scalari dovrebbe essere l'ultima risorsa per la maggior parte la progettazione di database problemi in SQL Server - semplicemente non sono buone prestazioni.

+0

l'udf dovrebbe verificare il valore del profilo dell'entità per l'ID passato, se null restituisce false else restituisce true – Yasmine

4

Se il il modo in cui determini se un'entità ha un profilo è una funzione deterministica e non richiede alcun accesso a un'altra tabella, potresti scrivere una funzione memorizzata e definire un campo calcolato e persistente che memorizzerebbe quel valore per te e non avrebbeper ricalcolarlo più e più volte.

Se è necessario eseguire una query su una tabella separata (ad esempio, controllare l'esistenza di una riga), si può ancora rendere questo "HasProfile" una colonna nella tabella delle entità e calcolare solo quel campo su base regolare, ad es. ogni notte o così. Se il valore è memorizzato come valore atomico, non è necessario il calcolo ogni volta. Questo funziona fintanto che questo fatto - ha un profilo o meno - non cambia troppo frequentemente.

Per aggiungere una colonna per verificare se EntityProfile è vuota, fare qualcosa di simile:

CREATE FUNCTION CheckHasProfile(@Field VARCHAR(MAX)) 
RETURNS BIT 
WITH SCHEMABINDING 
AS BEGIN 
    DECLARE @Result BIT 

    IF @Field IS NULL OR LEN(@Field) <= 0 
     SET @Result = 0 
    ELSE 
     SET @Result = 1 

    RETURN @Result 
END 

e quindi aggiungere una nuova colonna calcolata al vostro tavolo Entity:

ALTER TABLE dbo.Entity 
    ADD HasProfile AS dbo.CheckHasProfile(EntityProfile) PERSISTED 

Ora avere una colonna BIT ed è persistente, ad es non viene calcolato ogni volta per accedere alla riga e dovrebbe funzionare bene!

Problemi correlati