views:

3114

answers:

5

I'm Using SQL Server 2005.

The query would look like this

Select col1, col2, col3 from where (col1,col2) in

SQL Server doesn't seem to like that, any way of implementing that that anyone knows of that doesn't involve converting to varchars or anything else messy?

This is the actual query.

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
      )
+2  A: 

You have to separate in two clauses

 where col1 in (...) AND col2 in (...)

or you could refactor it a little bit

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
Eduardo Molteni
Seems a little excessive to do the same query twice
Stephen lacy
maybe, thats why I added some refactored code
Eduardo Molteni
nice work, but I have no idea how that "AS derivedtbl_1, Portal_GroupRoles, Portal_ClubGroup" thing works. Have a link or a name for it?
Stephen lacy
This is not a good answer: it fails to handle the requirement that col1 and col2 simultaneously match the same single row, and allows it to match if col1 matches any 1 row and col2 matches any 1 row.
Jonathan Leffler
It is called "I am old and started using MSSQL before it has the JOIN keyword" :) Seriously: it is a different way to do joins, you add the tables in the FROM clause and create the join in the WHERE clause
Eduardo Molteni
as derivedtbl_1 is just an alias for the union. The other two are the other tables in the join (pre SQL-92 syntax).
Bert Evans
@Eduardo: I'm OK with not using joins; I learned SQL before the join notation existed too. I've temporarily withdrawn my down-vote since the long query doesn't do what the short comment about two IN clauses suggests. That suggestion, though, is plain wrong. Please remove it, leaving just the OK bit.
Jonathan Leffler
@Jonathan: I'm sure if I follow you completely. I'm aware that the two IN clauses are not the same that the join. But in this case, I guess that this is what Selkie is trying to accomplish (of course it depends on the logic of the Selkie's app)
Eduardo Molteni
edit: I'm **not** sure if I...
Eduardo Molteni
@Eduardo: OK; let's pretend that it is OK - without input from Selkie, we can't be sure. (Meta-comment: if I make a typo in a comment and there's no response yet, I copy the typo version with control-C, delete the erroneous comment, and then add a new comment with the correction.)
Jonathan Leffler
@Jonathan: Ok, friends now :) BTW, thanks for the tip.
Eduardo Molteni
+2  A: 

Do a join on the derived table instead of using the 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
cmsjr
this is easy to read....
cgreeno
I did some formatting for him
Joel Coehoorn
Unfortunately I require a where clause to exist.Really I should have posted this but it should look likeSelect col1, col2, col3 from (subquery) where (col1,col2) in (subquery) OR col2 IS Null, won't work with a join.
Stephen lacy
A: 

Nevermind, that seemed to work.

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 IN 
  (
    SELECT  Portal_GroupRoles.RoleId
    FROM Portal_GroupRoles 
    INNER JOIN Portal_ClubGroups 
        ON Portal_GroupRoles.GroupId = Portal_ClubGroups.GroupId
    WHERE derivedtbl_1.ClubId = Portal_ClubGroups.ClubId
  )

You can reference a table outside of a subquery :)

Stephen lacy
That "seemed" to work? It answers a different question from the original query - is it the correct answer, always? It's clearly my morning to be the "grumpy old man".
Jonathan Leffler
replace seemed to work with worked. It was answer I was looking for.
Stephen lacy
A: 

The standard, classic way to do what you seek is an EXISTS clause:

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
  )

Be wary of splitting the two-column condition into two separate IN clauses; it does not give you the same answer (in general) as the applying the two-column condition in one EXISTS clause.

Jonathan Leffler
A: 
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
Michael Buen