2010-03-25 7 views
1

tblUserProfile - J'ai une table qui contient toutes les Info Profil (trop de champs)requête pour obtenir la ligne d'une table, une ligne autre au hasard d'un autre

tblMonthlyProfiles - Une autre table qui a juste le ProfileID dans (le idée est que cette table contient 2 profils qui deviennent parfois des profils mensuels (sur sélection)

Maintenant, quand j'ai besoin de montrer des profils mensuels, je fais simplement une sélection à partir de ce tblMonthlyProfiles et je joins avec tblUserProfile pour obtenir toutes les informations valides.

S'il n'y a aucune ligne dans tblMonthlyProfile, la section de profil mensuel n'est pas affichée.

Maintenant, l'exigence est de montrer TOUJOURS les profils mensuels. S'il n'y a pas de lignes dans monthlyProfiles, il doit récupérer 2 profils aléatoires de tblUserProfile. S'il n'y a qu'une seule ligne dans monthlyProfiles, elle ne doit récupérer qu'une seule ligne de tblUserProfile.

Quelle est la meilleure façon de faire tout cela en une seule requête?

Je pensais que quelque chose comme ça

sélectionner top 2 * de tblUserProfile P LEFT OUTER JOIN tblMonthlyProfiles M sur M.profileid = P.profileid Classez par NEWID()

Mais cela me donne toujours 2 lignes aléatoires de tblProfile. Comment puis-je resoudre ceci ?

Répondre

1

Essayez quelque chose comme ceci:

SELECT TOP 2 Field1, Field2, Field3, FinalOrder FROM 
(
select top 2 Field1, Field2, Field3, FinalOrder, '1' As FinalOrder from tblUserProfile P JOIN tblMonthlyProfiles M on M.profileid = P.profileid 
UNION 
select top 2 Field1, Field2, Field3, FinalOrder, '2' AS FinalOrder from tblUserProfile P LEFT OUTER JOIN tblMonthlyProfiles M on M.profileid = P.profileid ORDER BY NEWID() 
) 
ORDER BY FinalOrder 

L'idée étant de choisir deux profils mensuels (si ce nombre existe) et 2 profils aléatoires (comme vous l'avez fait correctement) et UNION eux. Vous aurez entre 2 et 4 enregistrements à ce moment-là. Prenez les deux premiers. La colonne FinalOrder est un moyen facile de s'assurer que vous essayez d'obtenir la première du mois.

Si vous contrôlez la structure de la table, vous pouvez vous éviter des problèmes en ajoutant simplement un champ booléen IsMonthlyProfile au tableau UserProfile. Ensuite, il est une requête de table unique, order by IsBoolean, NewID()

+0

En y regardant de plus près, je ne pense pas que le 2nd SELECT doive se joindre à la table mensuelle. Mais de toute façon j'espère que tu as l'idée. – LesterDove

+0

mais dans cette requête, où va le hasard? Les tables de profils ont des centaines d'enregistrements et j'ai juste besoin de 2 lignes aléatoires. –

+0

La deuxième requête aurait dû avoir le randomiseur NEWID(). Edité. – LesterDove

0

Dans la syntaxe compatible de SQL, vous pouvez faire quelque chose comme:

Select ... 
From (
     Select TOP 2 ... 
     From tblUserProfile As UP 
     Where Not Exists(Select 1 From tblMonthlyProfile As MP1) 
     Order By NewId() 
     ) As RandomProfile 
Union All 
Select MP.... 
From tblUserProfile As UP 
    Join tblMonthlyProfile As MP 
     On MP.ProfileId = UP.ProfileId 
Where (Select Count(*) From tblMonthlyProfile As MP1 ) >= 1 
Union All 
Select ... 
From (
     Select TOP 1 ... 
     From tblUserProfile As UP 
     Where (Select Count(*) From tblMonthlyProfile As MP1 ) = 1 
     Order By NewId() 
     ) As RandomProfile 

En utilisant SQL 2005+ CTE vous pouvez faire:

With 
    TwoRandomProfiles As 
    (
    Select TOP 2 ..., ROW_NUMBER() OVER (ORDER BY UP.ProfileID) As Num 
    From tblUserProfile As UP 
    Order By NewId() 
    ) 
Select MP.Col1, ... 
From tblUserProfile As UP 
    Join tblMonthlyProfile As MP 
     On MP.ProfileId = UP.ProfileId 
Where (Select Count(*) From tblMonthlyProfile As MP1 ) >= 1 
Union All 
Select ... 
From TwoRandomProfiles   
Where Not Exists(Select 1 From tblMonthlyProfile As MP1) 
Union All 
Select ... 
From TwoRandomProfiles 
Where (Select Count(*) From tblMonthlyProfile As MP1 ) = 1 
    And Num = 1 

Le CTE a l'avantage de ne demander qu'une seule fois les profils aléatoires et l'utilisation de la colonne ROW_NUMBER().

De toute évidence, dans toutes les instructions UNION, le nombre et le type des colonnes doivent correspondre.

Questions connexes