locked
How to retrive data from two tables RRS feed

  • Question

  • I had two tables having primary key as pkitem in tableA and fkitem in tableB

    1Q)From tableA need to know all rows that are not in tableB

    I tried couple of things but get diffrent results in these two ways 

    1.Select * from tableA a where pkitem NOT IN (select fkitem from tableB b where b.fkitem=a.pkitem AND b.starttime>=GETDATE())

    2.Select * from tableA a JOIN tableB b on b.fkitem=a.pkitem where b.starttime>GETDATE()

    what the diffrence between these two queries I dont get same rows when I run?

    I just need to find rows that are not in tableB which are future ones and insert them in tableB after disabling the triggers.But when I run the above two queries I see total number rows different, I am not sure if I was quering wrong?

    Any help appriciated


    satwick

    Saturday, February 25, 2012 12:04 AM

Answers

  • Hi Satwick,

    Let's see if we can make this clearer for you, by breaking it down.

    From your original question, you have 2 queries:

    SELECT * 
    FROM tableA a 
    WHERE pkitem NOT IN 
    	(	SELECT fkitem 
    		FROM tableB b 
    		WHERE b.fkitem=a.pkitem 
    		AND b.starttime>=GETDATE()
    	)

    This says get me all the rows from tableA where there is no matching record in tableB with a corresponding foreign key column matching tableA's primary key column AND the tableB record has a starttime now and in the future.  This will return any records in tableA that either do not have a tableB foreign key match at all, or does match to tableB but with a starttime on the tableB record which is in the past.

    This is functionally equivalent to Arbi's query:

    SELECT * 
    FROM tableA a 
    WHERE NOT EXISTS 
    	(	SELECT 1 
    		FROM tableB b 
    		WHERE b.fkitem=a.pkitem 
    		AND b.starttime>=GETDATE()
    	)

    Changing the "pkitem NOT IN" to "NOT EXISTS" makes it faster.  Also, since you are simply checking for existence, it doesn't matter what you return, hence returning "1" so the query processor doesn't even have to get a column back.

    Your second query was:

    SELECT * 
    FROM tableA a 
    JOIN tableB b 
    ON b.fkitem=a.pkitem 
    WHERE b.starttime>GETDATE()

    This says get me all the rows from tableA and tableB where each record in tableB contains a corresponding foreign key column matching tableA's primary key column AND the tableB record has a starttime only in the future.  This will return any records in tableA and in tableB where tableA primary key and tableB foreign key match, and a starttime on the tableB record which is in the future.  This can include duplicate tableA matches if there are more than one tableB match, and vice versa.

    Do you see now that those are 2 totally different queries, and that is why you get 2 different results?

    Now, you said:

    "I just need to find rows that are not in tableB which are future ones and insert them in tableB after disabling the triggers."

    Let's think about this for a second.  Where is the starttime column located? Is there one in tableA?  If not, then you already have records in tableB which are future ones, so why would you insert them again?

    If as in your earlier queries, the starttime column is only in tableB, then I think what you mean to say is:

    "I just need to find rows in tableB which are in the future that are not in tableA and insert them in tableA after disabling the triggers."

    In that case, here is your query:

    INSERT INTO tableA (
    	pkitem,
    	<other columns>
    )
    SELECT b.fkitem,
    	<other columns>
    FROM tableB b 
    WHERE b.starttime > GETDATE()
    AND NOT EXISTS 
    	(	SELECT 1 
    		FROM tableA a 
    		WHERE b.fkitem=a.pkitem
    	)

    Now, in your last post you mentioned:

    "another thing is I need to check any pkitem already booked for that particular time lets say i have two columns in tableB, TIMEfrom and timeTo"

    This would lead me to think there is a starttime column on tableA and not on tableB after all.  This would also make more sense since I can't imagine how you could have records in the child table that aren't in the parent table, unless they exist but with past starttimes.  In that case, I think what you mean to say is:

    "I just need to find rows in tableA which are future ones that are not in tableB and insert them in tableB after disabling the triggers."

    In that case, here is your query:

    INSERT INTO tableB (
    	fkitem,
    	timefrom,
    	timeto,
    	<other columns>
    )
    SELECT fkitem = a.pkitem,
    	timefrom = a.starttime,
    	timeto = <some value>,
    	<other columns>
    FROM tableA a 
    WHERE a.starttime > GETDATE()
    AND NOT EXISTS 
    	(	SELECT 1 
    		FROM tableB b 
    		WHERE b.fkitem=a.pkitem
    		AND a.starttime BETWEEN b.timefrom AND b.timeto
    	)
    Of course, not knowing the actual structure of your 2 tables makes this harder, but hopefully you now get the idea of how to frame the query.  Also, if you are truly using foreign key constraints, then disabling the triggers might not be enough.  Depending on the state your data is in, you may also want to temporarily drop these constraints as well while you are doing the insert.  I'm assuming that this is part of some initial data load.



    Diane



    • Edited by Diane Sithoo Thursday, March 1, 2012 10:14 PM
    • Marked as answer by satwick Thursday, March 1, 2012 10:50 PM
    • Unmarked as answer by satwick Thursday, March 8, 2012 11:05 PM
    • Marked as answer by satwick Sunday, March 11, 2012 1:00 PM
    Thursday, March 1, 2012 8:40 PM

All replies

  • Select * From TableA Where Not Exists (Select 1 From TableB Where TableA.PkItem = TableB.FKItem And TableB.StartTime > Current_timeStamp)
    
    --Or
    
    Select * 
    Form TableA 
    Left Outer Join TableB On TableA.PkItem = TableB.FKItem And TableB.StartTime > Current_timeStamp
    Where 
    TableB.fkItem is Null

    This would be like your first query. 

    Your second query is simple JOIN which will return only common records, NOT those that are not in tableB.


    Best Wishes, Arbi; Please vote if you find this posting was helpful or Mark it as answered.


    Saturday, February 25, 2012 12:08 AM
  • Hi I did same thing, 

    if i did 

    Select * From TableA Where Not Exists (Select 1 From TableB Where TableA.PkItem = TableB.FKItem

    And TableB.StartTime > Current_timeStamp)

    ------I get 200 rows

    If I execute query after braces I get more than 200 rows which is ideally not right, I think?


    satwick

    Saturday, February 25, 2012 12:21 AM
  • Does matter their StartTime? What is StartTime format? MM/dd/yyyy or Complete datatime format.

    Best Wishes, Arbi; Please vote if you find this posting was helpful or Mark it as answered.

    Saturday, February 25, 2012 12:23 AM
  • I did set dateformat dmy

    satwick

    Saturday, February 25, 2012 12:26 AM
  • Maybe:

    Select * From TableA Where Not Exists (Select 1 From TableB Where TableA.PkItem = TableB.FKItem 
    And Convert(Date, TableB.StartTime) > Convert(Date, Current_timeStamp))


    Best Wishes, Arbi; Please vote if you find this posting was helpful or Mark it as answered.

    Saturday, February 25, 2012 12:27 AM
  • If I run this 

    Select 1 From TableB Where TableA.PkItem = TableB.FKItem

    And TableB.StartTime > Current_timeStamp

    -------I get 3119 rows

    If I run the 

    Select * From TableA Where Not Exists (Select 1 From TableB Where TableA.PkItem = TableB.FKItem 

    And Convert(Date, TableB.StartTime) > Convert(Date, Current_timeStamp)) ----------------I should get same result why not?


    satwick

    Saturday, February 25, 2012 12:45 AM
  • Satwick, 

    Your query number one and my provided query are kind same. They will check if the record exist or NOT and will return the result set to you.

    1.Select * from tableA a where pkitem NOT IN (select fkitem from tableB b where b.fkitem=a.pkitem AND b.starttime>=GETDATE())

    Select * From TableA Where Not Exists (Select 1 From TableB Where TableA.PkItem = TableB.FKItem And TableB.StartTime > Current_timeStamp)

    Your Second query will check anything in common and will NOT check the differences. 

    2.Select * from tableA a JOIN tableB b on b.fkitem=a.pkitem where b.starttime>GETDATE()

    Difference is between in JOIN types.


    Best Wishes, Arbi; Please vote if you find this posting was helpful or Mark it as answered.

    Saturday, February 25, 2012 12:53 AM
  • After I found the results that are not in tableB, how to insert them into that table 

    another thing is I need to check any pkitem already booked for that particular time lets say i have two columns in tableB, TIMEfrom and timeTo


    satwick

    Thursday, March 1, 2012 7:49 PM
  • You will do something like this:

    Insert Into TableB (PKItem, FKItem, ...)
    Select * From TableA Where Not Exists (Select 1 From TableB Where TableA.PKItem = TableB.FKItem And Current_Timestamp Between TableB.TimeFrom And TableB.TimeTO)


    Best Wishes, Arbi; Please vote if you find this posting was helpful or Mark it as answered.

    Thursday, March 1, 2012 7:54 PM
  • Hi Satwick,

    Let's see if we can make this clearer for you, by breaking it down.

    From your original question, you have 2 queries:

    SELECT * 
    FROM tableA a 
    WHERE pkitem NOT IN 
    	(	SELECT fkitem 
    		FROM tableB b 
    		WHERE b.fkitem=a.pkitem 
    		AND b.starttime>=GETDATE()
    	)

    This says get me all the rows from tableA where there is no matching record in tableB with a corresponding foreign key column matching tableA's primary key column AND the tableB record has a starttime now and in the future.  This will return any records in tableA that either do not have a tableB foreign key match at all, or does match to tableB but with a starttime on the tableB record which is in the past.

    This is functionally equivalent to Arbi's query:

    SELECT * 
    FROM tableA a 
    WHERE NOT EXISTS 
    	(	SELECT 1 
    		FROM tableB b 
    		WHERE b.fkitem=a.pkitem 
    		AND b.starttime>=GETDATE()
    	)

    Changing the "pkitem NOT IN" to "NOT EXISTS" makes it faster.  Also, since you are simply checking for existence, it doesn't matter what you return, hence returning "1" so the query processor doesn't even have to get a column back.

    Your second query was:

    SELECT * 
    FROM tableA a 
    JOIN tableB b 
    ON b.fkitem=a.pkitem 
    WHERE b.starttime>GETDATE()

    This says get me all the rows from tableA and tableB where each record in tableB contains a corresponding foreign key column matching tableA's primary key column AND the tableB record has a starttime only in the future.  This will return any records in tableA and in tableB where tableA primary key and tableB foreign key match, and a starttime on the tableB record which is in the future.  This can include duplicate tableA matches if there are more than one tableB match, and vice versa.

    Do you see now that those are 2 totally different queries, and that is why you get 2 different results?

    Now, you said:

    "I just need to find rows that are not in tableB which are future ones and insert them in tableB after disabling the triggers."

    Let's think about this for a second.  Where is the starttime column located? Is there one in tableA?  If not, then you already have records in tableB which are future ones, so why would you insert them again?

    If as in your earlier queries, the starttime column is only in tableB, then I think what you mean to say is:

    "I just need to find rows in tableB which are in the future that are not in tableA and insert them in tableA after disabling the triggers."

    In that case, here is your query:

    INSERT INTO tableA (
    	pkitem,
    	<other columns>
    )
    SELECT b.fkitem,
    	<other columns>
    FROM tableB b 
    WHERE b.starttime > GETDATE()
    AND NOT EXISTS 
    	(	SELECT 1 
    		FROM tableA a 
    		WHERE b.fkitem=a.pkitem
    	)

    Now, in your last post you mentioned:

    "another thing is I need to check any pkitem already booked for that particular time lets say i have two columns in tableB, TIMEfrom and timeTo"

    This would lead me to think there is a starttime column on tableA and not on tableB after all.  This would also make more sense since I can't imagine how you could have records in the child table that aren't in the parent table, unless they exist but with past starttimes.  In that case, I think what you mean to say is:

    "I just need to find rows in tableA which are future ones that are not in tableB and insert them in tableB after disabling the triggers."

    In that case, here is your query:

    INSERT INTO tableB (
    	fkitem,
    	timefrom,
    	timeto,
    	<other columns>
    )
    SELECT fkitem = a.pkitem,
    	timefrom = a.starttime,
    	timeto = <some value>,
    	<other columns>
    FROM tableA a 
    WHERE a.starttime > GETDATE()
    AND NOT EXISTS 
    	(	SELECT 1 
    		FROM tableB b 
    		WHERE b.fkitem=a.pkitem
    		AND a.starttime BETWEEN b.timefrom AND b.timeto
    	)
    Of course, not knowing the actual structure of your 2 tables makes this harder, but hopefully you now get the idea of how to frame the query.  Also, if you are truly using foreign key constraints, then disabling the triggers might not be enough.  Depending on the state your data is in, you may also want to temporarily drop these constraints as well while you are doing the insert.  I'm assuming that this is part of some initial data load.



    Diane



    • Edited by Diane Sithoo Thursday, March 1, 2012 10:14 PM
    • Marked as answer by satwick Thursday, March 1, 2012 10:50 PM
    • Unmarked as answer by satwick Thursday, March 8, 2012 11:05 PM
    • Marked as answer by satwick Sunday, March 11, 2012 1:00 PM
    Thursday, March 1, 2012 8:40 PM
  • Thank you for the above responses,

    I had data in  table like this 

    2010-06-11 11:54:32

    2012-06-11 11:54:32 so on 

    How to filter them which are >than currentdate 


    satwick

    Thursday, March 1, 2012 9:21 PM
  • Hi satwick,

    If your column is called starttime, then use this:

    SELECT * FROM tableA 
    WHERE starttime > GETDATE()


    Diane

    Thursday, March 1, 2012 10:13 PM
  • 2010-06-11 11:54:32

    2012-06-11 11:54:32 so on 

    How to filter them which are >than currentdate 


    You can do the following with current midnight:

    DECLARE @Midnight datetime = 
          dateadd(day, datediff(day,0, CURRENT_TIMESTAMP), 0)
    SELECT @Midnight
    .....
    WHERE OrderDate > @Midnight

    More on date and time functions:
    http://www.sqlusa.com/bestpractices/datetimeconversion/


    Kalman Toth, SQL Server & Business Intelligence Training; SQL SERVER BEST PRACTICES

    Friday, March 9, 2012 1:49 PM