Запрос на получение строки из одной таблицы, иначе случайная строка из другой - PullRequest
1 голос
/ 25 марта 2010

tblUserProfile - у меня есть таблица, которая содержит всю информацию профиля (слишком много полей)

tblMonthlyProfiles - еще одна таблица, в которой есть только ProfileID (идея состоит в том, что эта таблица содержит 2 профили, которые иногда становятся ежемесячными (при выборе))

Теперь, когда мне нужно показать месячные профили, я просто делаю выбор из этого tblMonthlyProfiles и присоединяюсь к tblUserProfile, чтобы получить всю достоверную информацию.

Если в tblMonthlyProfile нет строк, раздел месячного профиля не отображается.

Теперь необходимо ВСЕГДА показывать ежемесячные профили. Если в ежемесячных профилях нет строк, он должен выбрать 2 случайных профиля из tblUserProfile. Если в ежемесячных профилях есть только одна строка, она должна выбрать только одну случайную строку из tblUserProfile.

Каков наилучший способ сделать все это в одном запросе?

Я думал, что-то вроде этого

выберите топ 2 * из tblUserProfile P СЛЕДУЮЩЕЕ НАРУЖНОЕ СОЕДИНЕНИЕ tblMonthlyProfiles M на M.profileid = P.profileid ЗАКАЗАТЬ по NEWID ()

Но это всегда дает мне 2 случайных строки из tblProfile. Как я могу решить это?

Ответы [ 2 ]

1 голос
/ 25 марта 2010

Попробуйте что-то вроде этого:

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

Идея состоит в том, чтобы выбрать два ежемесячных профиля (если таковых существует), а затем 2 случайных профиля (как вы правильно сделали) и затем ОБЪЕДИНИТЬ их. В этот момент у вас будет от 2 до 4 записей. Хватай две верхние. Столбец FinalOrder - это простой способ убедиться, что вы пытаетесь получить ежемесячную первую.

Если у вас есть контроль над структурой таблицы, вы можете избежать некоторых проблем, просто добавив логическое поле IsMonthlyProfile в таблицу UserProfile. Тогда это запрос к одной таблице, order by IsBoolean, NewID()

0 голосов
/ 25 марта 2010

В SQL 2000+ совместимом синтаксисе вы можете сделать что-то вроде:

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

Используя SQL 2005+ CTE, вы можете:

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

Преимущество CTE состоит в том, что один раз запрашиваются случайные профили и используется столбец ROW_NUMBER ().

Очевидно, что во всех операторах UNION число и тип столбцов должны совпадать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...