How to select data in t-sql

  • Hi,

    My table structure is like this.

    TABLE: TEST

    ID countries

    100 IN, AU, GB, FR

    101 GB, FR, IN

    102 IN, AU

    103 AU, GB

    104 GB, FR, IN, AU

    I want to extract the ids that have "IN" AND "AU" only.

    But when I run this query, it brings all ids that have "IN" OR "AU"

    SELECT ID FROM TEST

    WHERE COUNTRIES IN ('IN', 'AU')

    The result is

    ID

    100

    101

    102

    103

    104

    The result I expect to see is

    ID

    100

    102

    104

    only.

    Please help.

    Thank you in advance.

  • Well I am going to assume that you table structure description is incorrect, and the your query attempt reflects that actual structure of your data.

    If so, then this should do it:

    SELECT ID

    FROM TEST

    WHERE ID IN (Select t2.ID From TEST t2

    Where t2.COUNTRIES='AU')

    AND COUNTRIES = 'IN'

    edit: typo

    [font="Times New Roman"]-- RBarryYoung[/font], [font="Times New Roman"] (302)375-0451[/font] blog: MovingSQL.com, Twitter: @RBarryYoung[font="Arial Black"]
    Proactive Performance Solutions, Inc.
    [/font]
    [font="Verdana"] "Performance is our middle name."[/font]

  • jmucherla (3/9/2009)


    Hi,

    My table structure is like this.

    TABLE: TEST

    ID countries

    100 IN, AU, GB, FR

    101 GB, FR, IN

    102 IN, AU

    103 AU, GB

    104 GB, FR, IN, AU

    I want to extract the ids that have "IN" AND "AU" only.

    But when I run this query, it brings all ids that have "IN" OR "AU"

    SELECT ID FROM TEST

    WHERE COUNTRIES IN ('IN', 'AU')

    Barry is correct... that query won't give you any results against the data table you've listed. Which is correct? The table you have listed or the query?

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • My table structure is actually like this.

    TABLE: TEST

    ID Countries

    100 IN

    100 AU

    100 GB

    100 FR

    101 GB

    101 GB

    101 FR

    101 IN

    102 IN

    102 AU

    103 AU

    103 GB

    104 GB

    101 FR

    101 IN

    101 AU

  • If you want to exclude those ID's that have other countries besides AU and IN then use this:

    SELECT ID

    FROM TEST

    WHERE ID IN (Select t2.ID From TEST t2 Where t2.COUNTRIES='AU')

    AND COUNTRIES = 'IN'

    AND ID NOT IN (Select t3.ID From TEST t3 Where t3.COUNTRIES not in ('AU', 'IN'))

    Bevan

  • Or this works as well:

    Select t3.ID From #TEST t3 Where t3.COUNTRIES in ('AU', 'IN')

    except

    Select t3.ID From #TEST t3 Where t3.COUNTRIES not in ('AU', 'IN')

    Looks slower based on execution plan but I'm not sure what it would do over big recordsets.

    Bevan

  • or slightly fast if there is a clustered primary key on ID and countries...

    Bevan

  • Bevan keighley (3/9/2009)


    Or this works as well:

    Select t3.ID From #TEST t3 Where t3.COUNTRIES in ('AU', 'IN')

    except

    Select t3.ID From #TEST t3 Where t3.COUNTRIES not in ('AU', 'IN')

    Looks slower based on execution plan but I'm not sure what it would do over big recordsets.

    Bevan

    Try it against the data posted... won't return what the op requested.

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • jmucherla (3/9/2009)


    My table structure is actually like this.

    TABLE: TEST

    ID Countries

    100 IN

    100 AU

    100 GB

    100 FR

    101 GB

    101 GB

    101 FR

    101 IN

    102 IN

    102 AU

    103 AU

    103 GB

    104 GB

    101 FR

    101 IN

    101 AU

    In the future, if you could make that look like the following, it would be a huge help...

    CREATE TABLE #Test

    (ID INT, Countries CHAR(2))

    INSERT INTO #Test

    (ID, Countries)

    SELECT '100','IN' UNION ALL

    SELECT '100','AU' UNION ALL

    SELECT '100','GB' UNION ALL

    SELECT '100','FR' UNION ALL

    SELECT '101','GB' UNION ALL

    SELECT '101','GB' UNION ALL

    SELECT '101','FR' UNION ALL

    SELECT '101','IN' UNION ALL

    SELECT '102','IN' UNION ALL

    SELECT '102','AU' UNION ALL

    SELECT '103','AU' UNION ALL

    SELECT '103','GB' UNION ALL

    SELECT '104','GB' UNION ALL

    SELECT '104','FR' UNION ALL

    SELECT '104','IN' UNION ALL

    SELECT '104','AU'

    See the link in my signature for how to do that easily... you'll get better answers quicker.

    Based on that, Barry's code will do the trick.

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • ... And, if the combination of ID and Countries forms unique pairs, here's another way that's super easy to expand to additional countries...

    SELECT ID

    FROM #Test

    WHERE Countries IN ('IN','AU')

    GROUP BY ID

    HAVING COUNT(*) = 2

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • You may need to use this in case duplicates are allowed

    SELECT ID

    FROM #Test

    WHERE Countries IN ('IN','AU')

    GROUP BY ID

    HAVING COUNT(DISTINCT Countries) = 2


    Madhivanan

    Failing to plan is Planning to fail

  • Jeff Moden (3/9/2009)


    Bevan keighley (3/9/2009)


    Or this works as well:

    Select t3.ID From #TEST t3 Where t3.COUNTRIES in ('AU', 'IN')

    except

    Select t3.ID From #TEST t3 Where t3.COUNTRIES not in ('AU', 'IN')

    Looks slower based on execution plan but I'm not sure what it would do over big recordsets.

    Bevan

    Try it against the data posted... won't return what the op requested.

    Hmmmmm, I think this is a case of unclear requirements! (seen that before!)

    I want to extract the ids that have "IN" AND "AU" only.

    I read this as: "IN" AND "AU" AND nothing else. It would be good to know the OP's actual intentions here.

    Bevan

  • Yeah... I agree... the written requirements weren't that clear. The desired return posted along with the attempted code and the existing data was the key.

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • Here is another possible solution:

    CREATE TABLE #Test

    (ID INT, Countries CHAR(2));

    INSERT INTO #Test

    (ID, Countries)

    SELECT '100','IN' UNION ALL

    SELECT '100','AU' UNION ALL

    SELECT '100','GB' UNION ALL

    SELECT '100','FR' UNION ALL

    SELECT '101','GB' UNION ALL

    SELECT '101','GB' UNION ALL

    SELECT '101','FR' UNION ALL

    SELECT '101','IN' UNION ALL

    SELECT '102','IN' UNION ALL

    SELECT '102','AU' UNION ALL

    SELECT '103','AU' UNION ALL

    SELECT '103','GB' UNION ALL

    SELECT '104','GB' UNION ALL

    SELECT '104','FR' UNION ALL

    SELECT '104','IN' UNION ALL

    SELECT '104','AU';

    with ID_Countries (

    ID,

    CountryIDs

    ) as (

    select

    ID,

    stuff((select ',' + Countries from #Test T2 where T2.ID = T1.ID for xml path ('')),1,1,'')

    from

    #Test T1

    group by

    ID

    )

    select

    ID

    from

    ID_Countries

    where

    CountryIDs like '%IN%' and

    CountryIDs like '%AU%'

    ;

    drop table #Test;

  • And, just for S&G's here is another alternative:

    CREATE TABLE #Test

    (ID INT, Countries CHAR(2));

    INSERT INTO #Test

    (ID, Countries)

    SELECT '100','IN' UNION ALL

    SELECT '100','AU' UNION ALL

    SELECT '100','GB' UNION ALL

    SELECT '100','FR' UNION ALL

    SELECT '101','GB' UNION ALL

    SELECT '101','GB' UNION ALL

    SELECT '101','FR' UNION ALL

    SELECT '101','IN' UNION ALL

    SELECT '102','IN' UNION ALL

    SELECT '102','AU' UNION ALL

    SELECT '103','AU' UNION ALL

    SELECT '103','GB' UNION ALL

    SELECT '104','GB' UNION ALL

    SELECT '104','FR' UNION ALL

    SELECT '104','IN' UNION ALL

    SELECT '104','AU';

    declare @TestVals varchar(32);

    set @TestVals = ',' + 'IN,AU' +',';

    with

    a1 as (select 1 as N union all

    select 1 union all

    select 1 union all

    select 1 union all

    select 1 union all

    select 1 union all

    select 1 union all

    select 1 union all

    select 1 union all

    select 1),

    a2 as (select

    1 as N

    from

    a1 as a

    cross join a1 as b),

    a3 as (select

    1 as N

    from

    a2 as a

    cross join a2 as b),

    a4 as (select

    1 as N

    from

    a3 as a

    cross join a2 as b),

    Tally as (select

    row_number() over (order by N) as N

    from

    a4),

    CheckCountries(

    Countries

    ) as (

    SELECT

    SUBSTRING(@TestVals,N + 1,CHARINDEX(',',@TestVals,N + 1) - N - 1)

    FROM

    Tally

    WHERE

    N < LEN(@TestVals)

    AND SUBSTRING(@TestVals,N,1) = ',' --Notice how we find the comma

    ),

    UniqueCountries (

    CountryCnt

    ) as (

    select

    count(distinct Countries)

    from

    CheckCountries

    )

    select

    ID

    from

    #Test t

    inner join CheckCountries cc

    on (t.Countries = cc.Countries)

    cross join UniqueCountries uc

    group by

    ID,

    uc.CountryCnt

    having

    count(distinct t.Countries) = uc.CountryCnt

    drop table #Test;

Viewing 15 posts - 1 through 15 (of 19 total)

You must be logged in to reply to this topic. Login to reply