views:

53

answers:

4

Hi Experts,

I'm tryin to join two tables. The problem i'm having is that one of the columns i'm trying to join on is a list.

So is it possible to join two tables using "IN" rather than "=". Along the lines of

SELECT ID  
FROM tableA INNER JOIN  
tableB ON tableB.misc IN tableA.misc  
WHERE tableB.miscTitle = 'help me please'  


tableB.misc = 1  
tableA.misc = 1,2,3  

Thanks in advance

+1  A: 

Try this:

SELECT ID  
FROM tableA INNER JOIN  
tableB ON ',' + TableA.misc + ',' like '%,' + cast(tableB.misc as varchar) + ',%'
WHERE tableB.miscTitle = 'help me please'  
Denis Valeev
I've tried this but i'm now getting the following error.
James
Conversion failed when converting the varchar value ',' to data type int.
James
this is what my SQL now looks like SELECT DISTINCT CTListings.CTListingId FROM CTListings INNER JOIN tusers ON (CTListings.userId = tusers.UserID) INNER JOIN CTListingCat ON ',' + CTListingCat.listingCatID+ ',' like '%,' + cast(CTListings.companyCategories as varchar) + ',%' WHERE 0 = 0 AND isLive = ? AND CTListingCat.listing = ?
James
sorry about the layout, but I don't know how to format the code
James
@James, it's the other way around, sorry for the confusion. You need to embrace the id thingy in the cast statement instead of your varchar column.
Denis Valeev
@James, see how it's tableB.misc being cast as int and not the tableA.misc which is a list (varchar) which doesn't need to be cast as varchar.
Denis Valeev
Hi Denis, Thanks for your help but I've come to the conclusion that it was lazy design that got me in this mess. I will now change the structure of the DB to have a lookup table rather then storing the ids in a list.
James
A: 

Is ID also in tableB? If so, you can reverse the tables, and run the IN backwards, in the WHERE section, like so:

SELECT ID
FROM tableB
WHERE tableB.miscTitle = 'help me please'
    AND tableB.misc IN (SELECT tableA.misc FROM tableA)

If it's not, you could use a cross join to get all combinations of rows between the tables, then remove the rows that don't obey the IN. WARNING: This will become a huge join if the tables are large. Example:

SELECT ID
FROM tableA
CROSS JOIN tableB
WHERE tableB.miscTitle = 'help me please'
    AND tableB.misc IN tableA.misc

EDIT: didn't realize "in a list" meant a comma-delimited VARCHAR. SQL's IN won't work for that, nor should you ever store joinable data that way in a database.

ChessWhiz
unfortunatly the ID is in tableA
James
Edited in CROSS JOIN option.
ChessWhiz
+5  A: 

No what you want is not possible without a major workaround. DO NOT STORE ITEMS YOU WANT TO JOIN TO IN A LIST! In fact a comma delimited list should almost never be stored in a database. It is only acceptable if this is note type information that will never need to be used in a query where clasue or join.

If you are stuck with this horrible design, then you will have to parse out the list to a temp table or table variable and then join through that.

HLGEM
I agree, there are solutions like mentioned below, but first design should be right, if you can make that change
Nitin Midha
Thanks for your. Your right, I was being lazy when I was creating the tables. I will re-design them.
James
+1  A: 

A string parsing function like the one found here together with a CROSS APPLY should do the trick.

CREATE FUNCTION [dbo].[fnParseStringTSQL] (@string NVARCHAR(MAX),@separator NCHAR(1))
RETURNS @parsedString TABLE (string NVARCHAR(MAX))
AS 
BEGIN
   DECLARE @position int
   SET @position = 1
   SET @string = @string + @separator
   WHILE charindex(@separator,@string,@position) <> 0
      BEGIN
         INSERT into @parsedString
         SELECT substring(@string, @position, charindex(@separator,@string,@position) - @position)
         SET @position = charindex(@separator,@string,@position) + 1
      END
     RETURN
END
go

declare @tableA table (
    id int,
    misc char(1)
)

declare @tableB table (
    misc varchar(10),
    miscTitle varchar(20)
)

insert into @tableA
    (id, misc)
    values
    (1, '1')

insert into @tableB
    (misc, miscTitle)
    values
    ('1,2,3','help me please')

select id
    from @tableB b
        cross apply dbo.fnParseStringTSQL(b.misc,',') p
        inner join @tableA a
            on a.misc = p.string
    where b.miscTitle = 'help me please'

drop function dbo.fnParseStringTSQL
Joe Stefanelli