Answered by:
How to retrive data from two tables

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.
- Edited by Arbi Baghdanian Saturday, February 25, 2012 12:09 AM
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
- Proposed as answer by Mohamed Irshad Friday, March 9, 2012 2:45 PM
Friday, March 9, 2012 1:49 PM