Я использую SQL Server 2005.
Запрос будет выглядеть так
Select col1, col2, col3 from <subquery> where (col1,col2) in <subquery>
SQL Server, похоже, это не нравится. Любой способ реализовать это, о котором кто-то знает, не включает преобразование в varchars или что-то еще беспорядочное?
Это фактический запрос.
SELECT *
FROM
(
SELECT NEWID() AS guid, UserID, RoleId, ClubId, 0 AS GroupRole
FROM dbo.Portal_UserRoles
UNION
SELECT NEWID() AS guid, dbo.Portal_UserGroups.UserId,
dbo.Portal_GroupRoles.RoleId, dbo.Portal_UserGroups.ClubId,
dbo.Portal_GroupRoles.GroupId AS GroupRole
FROM dbo.Portal_GroupRoles
INNER JOIN dbo.Portal_UserGroups
ON dbo.Portal_GroupRoles.GroupId = dbo.Portal_UserGroups.GroupId
) AS derivedtbl_1
WHERE (derivedtbl_1.RoleId,derivedtbl_1.ClubId) IN
(
SELECT Portal_GroupRoles.RoleId, Portal_ClubGroups.ClubId
FROM Portal_GroupRoles
INNER JOIN Portal_ClubGroups
ON Portal_GroupRoles.GroupId = Portal_ClubGroups.GroupId
)
Извините, я не знаю, как это сделать.
Как ни странно, этот вопрос набрал почти 3 тыс. Просмотров и ни разу не проголосовал за него.


Вы должны разделить на два пункта
where col1 in (...) AND col2 in (...)
или вы можете немного реорганизовать его
select * FROM (
SELECT NEWID() AS guid, UserID, RoleId, ClubId, 0 AS GroupRole FROM dbo.Portal_UserRoles
UNION
SELECT NEWID() AS guid, dbo.Portal_UserGroups.UserId, dbo.Portal_GroupRoles.RoleId, dbo.Portal_UserGroups.ClubId, dbo.Portal_GroupRoles.GroupId AS GroupRoles FROM dbo.Portal_GroupRoles INNER JOIN dbo.Portal_UserGroups ON dbo.Portal_GroupRoles.GroupId = dbo.Portal_UserGroups.GroupId)
AS derivedtbl_1, Portal_GroupRoles, Portal_ClubGroup
where derivedtbl_1.RoleId = Portal_GroupRoles.RoleId
and derivedtbl_1.ClubId = Portal_ClubGroups.ClubId
and Portal_GroupRoles.GroupId = Portal_ClubGroups.GroupId
Кажется немного чрезмерным повторять один и тот же запрос дважды
отличная работа, но я понятия не имею, как работает эта штука "AS производныеtbl_1, Portal_GroupRoles, Portal_ClubGroup". У вас есть ссылка или название?
Это нехороший ответ: он не справляется с требованием, чтобы col1 и col2 одновременно соответствовали одной и той же строке, и позволяет ему соответствовать, если col1 соответствует любой 1 строке, а col2 соответствует любой 1 строке.
Это называется «Я стар и начал использовать MSSQL до того, как у него появилось ключевое слово JOIN» :) Серьезно: это другой способ объединения, вы добавляете таблицы в предложение FROM и создаете соединение в предложении WHERE
поскольку производный tbl_1 - это просто псевдоним союза. Две другие - это другие таблицы в объединении (синтаксис до SQL-92).
@Eduardo: Я не против не использовать объединения; Я изучал SQL до того, как появилась нотация соединения. Я временно отозвал свой голос против, поскольку длинный запрос не делает того, что предлагает короткий комментарий о двух предложениях IN. Однако это предположение совершенно неверно. Удалите его, оставив только бит ОК.
@Jonathan: Я уверен, что полностью за вами следую. Я знаю, что два предложения IN - это не то же самое, что соединение. Но в данном случае я предполагаю, что это то, чего пытается достичь Селки (конечно, это зависит от логики приложения Селки)
@ Эдуардо: Хорошо; давайте сделаем вид, что это нормально - без участия Селки мы не можем быть уверены. (Мета-комментарий: если я допущу опечатку в комментарии, а ответа еще нет, я копирую версию с опечаткой с помощью Ctrl-C, удаляю ошибочный комментарий, а затем добавляю новый комментарий с исправлением.)
Выполните соединение производной таблицы вместо использования in
SELECT *
FROM
(
SELECT NEWID() AS guid, UserID, RoleId, ClubId, 0 AS GroupRole
FROM dbo.Portal_UserRoles
UNION
SELECT NEWID() AS guid, dbo.Portal_UserGroups.UserId,
dbo.Portal_GroupRoles.RoleId, dbo.Portal_UserGroups.ClubId,
dbo.Portal_GroupRoles.GroupId AS GroupRole
FROM dbo.Portal_GroupRoles
INNER JOIN dbo.Portal_UserGroups
ON dbo.Portal_GroupRoles.GroupId = dbo.Portal_UserGroups.GroupId
) AS derivedtbl_1
INNER JOIN
(
SELECT Portal_GroupRoles.RoleId, Portal_ClubGroups.ClubId
FROM Portal_GroupRoles
INNER JOIN Portal_ClubGroups
ON Portal_GroupRoles.GroupId = Portal_ClubGroups.GroupId
) derivedtbl_2
ON derivedtbl_1.RoleID = derivedtbl_2.RoleID
AND derivedtbl_1.ClubId = derivedtbl_2.ClubId
К сожалению, мне нужно, чтобы предложение where существовало. На самом деле я должен был опубликовать это, но он должен выглядеть так: Select col1, col2, col3 from (subquery), where (col1, col2) in (subquery) OR col2 IS Null, не будет работать с соединением.
Стандартный классический способ делать то, что вы ищете, - это предложение EXISTS:
SELECT *
FROM
(
SELECT NEWID() AS guid, UserID, RoleId, ClubId, 0 AS GroupRole
FROM dbo.Portal_UserRoles
UNION
SELECT NEWID() AS guid, dbo.Portal_UserGroups.UserId,
dbo.Portal_GroupRoles.RoleId, dbo.Portal_UserGroups.ClubId,
dbo.Portal_GroupRoles.GroupId AS GroupRole
FROM dbo.Portal_GroupRoles
INNER JOIN dbo.Portal_UserGroups
ON dbo.Portal_GroupRoles.GroupId = dbo.Portal_UserGroups.GroupId
) AS derivedtbl_1
WHERE EXISTS
(
SELECT Portal_GroupRoles.RoleId, Portal_ClubGroups.ClubId
FROM (Portal_GroupRoles
INNER JOIN Portal_ClubGroups
ON Portal_GroupRoles.GroupId = Portal_ClubGroups.GroupId) AS cgr
WHERE derivedtbl_1.RoleID = cgr.RoleId
AND derivedtbl_1.ClubId = cgr.ClubId
)
Будьте осторожны при разделении условия с двумя столбцами на два отдельных предложения IN; он не дает того же ответа (в общем), как применение условия двух столбцов в одном предложении EXISTS.
SELECT
/*
your selected fields, joins here
*/
WHERE -- (derivedtbl_1.RoleId,derivedtbl_1.ClubId) IN
EXISTS
(
-- actually you can change these two fields to * (asterisk ) or 1, whatever, even your name, what matters only is the testing of existence(see below)
SELECT Portal_GroupRoles.RoleId, Portal_ClubGroups.ClubId
FROM Portal_GroupRoles
INNER JOIN Portal_ClubGroups
ON Portal_GroupRoles.GroupId = Portal_ClubGroups.GroupId
-- here is your IN (the testing of existence):
WHERE Portal_GroupRoles.RoleId = derivedtbl_1.RoleId AND
AND derivedtbl_1.ClubId = derivedtbl_1.ClubId
)
alternatively:
SELECT
/*
your selected fields, joins here
*/
JOIN
(
SELECT Portal_GroupRoles.RoleId, Portal_ClubGroups.ClubId
FROM Portal_GroupRoles
INNER JOIN Portal_ClubGroups
ON Portal_GroupRoles.GroupId = Portal_ClubGroups.GroupId
) X
-- here is your IN:
ON X.RoleId = derivedtbl_1.RoleId
AND X.ClubId = derivedtbl_1.ClubId
Ваш полезный синтаксис поддерживается в стандартном SQL. Он еще не реализован в SQL Server, но вы можете проголосовать за его включение здесь.
onedaywhen дает лучший ответ, если вы переходите из среды Oracle в среду сервера sql. Однозначного ответа нет. Иногда это полезный запрос, даже если у вас есть хорошо нормализованная база данных. Стандарт SQL? Какой стандарт SQL? Я приветствую postgresql за то, что он заранее предупредил вас, что они следуют стандарту или нет, или реализуют ли они расширение стандарта.
Это поможет людям помочь вам, если вы отформатируете это более читабельно.