'dynamic' SQL join possible? - sql

I have a table Action with a (part of the) structure like this:
Action:
ActionTypeID,
ActionConnectionID
...
ActionTypeID refers to types 1-5 which correspond to different tables (1=Pro, 2=Project etc.)
ActionConnectionID is the primaryKey in the corresponding table;
ie. ActionTypeID=1,
ActionConnectionID=43 -> would point
to Pro.ProID=43 and ActionTypeID=2,
ActionConnectionID=233 -> would point
to Project.ProjectID=233
Is there a way to 'dynamically join the different tables depending on the value in the ActionTypeID column?
ie. for records with the ActionTypeID=1 this would be:
Select Action.*
From Action Left Join Pro On Action.ActionConnectionID=Pro.ProID
for records with the ActionTypeID=2 this would be:
Select Action.*
From Action Left Join Project On Action.ActionConnectionID=Project.ProjectID
etc.
If this is not possible to accomplish in one query I will have to loop over all the possible ActionTypes and perform the query and then afterwards join the data in one query again - that would be possible, but doesnt sound like the most efficient way :-)

Something like this should do:
Select Action.*
From Action
Left Join Pro
ON Action.ActionConnectionID=Pro.ProID and ActionTypeID=1
Left Join Project
ON Action.ActionConnectionID=Project.ProjectID and ActionTypeID=2
If that doesn't work for either try using dynamic sql which is a bad solution or properly normalize your data.

Are you just trying to select everything without any filters at all? I always hate when people give answers that are basically "don't do t like that, do it like this instead" but now I'm going to go ahead and do that myself. Have you considered a different schema where you don't have to write this kind of query? I assume that the Pro, Project, etc, tables all have the same schema - can they be combined into one table? Perhaps you don't have control over that and are working with a DB you can't change (been there myself). You should explore using UNION to join up the pieces that you need.
(Select Action.*
From Action Left Join Pro On Action.ActionConnectionID=Pro.ProID)
UNION
(Select Action.*
From Action Left Join Project On Action.ActionConnectionID=Project.ProjectID)

Related

Natural Joins Creating More Records Than Desired

I have the following tables populated with these records:
I have created a view that looks like this and have selected all records from it:
However, the results are not as expected. Each store location is matched with each craft item, even if they are not supplied to that store.
Even regions that don't have recorded stores display records:
I imagine this has something to do with the natural join being mixed with the left outer join, but I don't understand why.
And based on all the comments others have provided, and you may not be comfortable explicitly with the syntax, think of LEFT side as the first table of a query and right is the second. So a left join implies everything from the left-side table regardless of a match on the other, but if one exists, it only exists based on the matching criteria/condition. For what you have, you are probably looking for something like...
create or replace view detailedCraftRegaion as
select
cr.CraftRegionDescription,
cs.StoreAddress,
cs.StoreCity,
cs.StoreState,
cs.StoreZipCode,
csi.CraftItemName
from
CraftStore cs
JOIN CraftRegion cr
on cs.CraftRegionID = cr.CraftRegionID
JOIN CraftShipItems csi
on cs.CraftStoreID = csi.CraftStoreID

How to Select Specific data on query with RIGHT JOIN statement?

I am joining 2 tables using RIGHT JOIN statement. I used below query and it works good. However it still display all data whenever I tried to select specific user
SELECT TBLNOTIFICATIONS.NOTIFICATION_ID, TBLNOTIFICATIONS.NOTIFICATION_TYPE, FILENAMES_LIST.LOCATION_FILENAME, TBLNOTIFICATIONS.NOTIFICATION_DATE
FROM TBLNOTIFICATIONS
RIGHT JOIN FILENAMES_LIST
ON TBLNOTIFICATIONS.NOTIFICATION_ID=FILENAMES_LIST.NOTIFICATION_ID
WHERE TBLNOTIFICATIONS.USER_ID='JCON'
What should I do to select data from specific user?
Thanks in advance.
You are filtering on the left table, so all the data of the right table will still be shown.
It is probably enough to change the query to a LEFT JOIN to get the results you want.
Besides that, you can use aliases to make your query more readable, like so:
SELECT tn.NOTIFICATION_ID, tn.NOTIFICATION_TYPE, fl.LOCATION_FILENAME, tn.NOTIFICATION_DATE
FROM TBLNOTIFICATIONS AS tn
LEFT JOIN FILENAMES_LIST AS fl
ON tn.NOTIFICATION_ID = fl.NOTIFICATION_ID
WHERE tn.USER_ID='JCON'

SQL Server: select over several tables / conditions

Okay, I'm relatively new to the more advanced uses of SQL Server.
I have several tables that I need to gather informations from, and several of these tables links to other tables where I need a specific information. As a result, I just want one row with all the information, preferential named with aliases.
For example:
Tab_Transcoders:
ID, VideoCamID, InputStreamID, OutputStreamID.
where InputStream links to another table where I need the row of the matching ID, where in this row are other ID's (e.g. StreamType_ID that belongs to a third table containing ID_StreamType and Description etc.)
Same with OutputStreamID, same with VideoCamID.
In the end, I need a row containing for example:
ID, VideoCamID, InputStreamID, InputStreamType, InputStreamTypeDesc,
OutputStreamID, OutputStreamType, OutputStreamDesc, VideoCamID, etc. etc. etc.
It is important for me that I can set aliases, as for example InputStreamID & OutputStreamID links to the same table where all my Streams are listed (with IP's, Descs..)
I can accomplish this with doing like 100 SELECTS & SUBSELECTS, but I don't think that's an appropriate way.
I read some informations about things like CURSOR, UNION, FETCH, JOIN etc. etc.. but I don't know which one I have to use for my purpose.
eli
I think you want something like the following....
Select
t.ID,
t.VideoCamID,
i.InputStreamID,
is.StreamType as InputStreamType,
is.StreamDesc as InputStreamDesc,
o.OutputStreamID,
os.StreamType as OutputStreamType,
os.StreamDesc as OutputStreamDesc,
v.VideoCamID
from
Tab_Transcoders t
inner join InputStreams i on i.InputStreamID=t.InputStreamId
inner join Streams is on is.StreamId=i.StreamId
inner join OutputStreams o on o.OutputStreamId=t.OutputStreamId
inner join Streams os on os.StreamID=o.StreamId
inner join VideoCams v on v.VideoCamId=t.VideoCamID
If there is a defined relationship between your tables, then Use Join.
e.g Customer Order
Order will have customer Id
Select Order.ID,Order.Quantity, Order.CustomerId, Customer.FullName, Customer.Address
From Orders Order
Join
Customer
On
Order.CustomerId = Customer.CustomerId
First start by getting data from two tables using the join and then if it works as per your requirement, add another required table in the join.
Read about SQl JOINS.. It is fairly simple.
I will recommend reading you some of the articles around CTE aka Common Table Expression.
Refer http://msdn.microsoft.com/en-us/library/ms190766%28v=sql.105%29.aspx.
Apart from this never use subqueries. Try to use inner join / any other join if possible.

methods of joining 2 tables without using JOIN or SELECT more than one distinct table in the query

Is there a way of joining results from 2 tables without using JOIN or SELECT from more than one table? The reason being the database im working with requires queries that only contain SELECT, FROM, and WHERE clauses containing only one distinct table. I do, however, need information from other tables for the project i'm working on.
More info: the querier returns the query results in a .csv format, is there something we can manipulate there?
Pick a programming language. Any language will do. Run one query, and get the results. Run another query, get the results. Use the programming language to combine the results.
Seriously. You are asking how to join data from a database that doesn't support joins. If the database doesn't support it, you're going to have to do it externally.
select a.*, b.* from tablea a, tableb b
You can do it either by Using JOIN or SELECT. You have to use one of it. By Join you must be knowing. I am writing an example for without using JOIN and just using SELECT, to join two tables.
SELECT * from Table1, Table2 where Table1.common_attribute = Table2.common_attribute;

SELECT with ORs including table joins

I've got a database with three tables: Books (with book details, PK is CopyID), Keywords (list of keywords, PK is ID) and KeywordsLink which is the many-many link table between Books and Keywords with the fields ID, BookID and KeywordID.
I'm trying to make an advanced search form in my app where you can search on various criteria. At the moment I have it working with Title, Author and Publisher (all from the Book table). It produces SQL like:
SELECT * FROM Books WHERE Title Like '%Software%' OR Author LIKE '%Spolsky%';
I want to extend this search to also search using tags - basically to add another OR clause to search the tags. I've tried to do this by doing the following
SELECT *
FROM Books, Keywords, Keywordslink
WHERE Title LIKE '%Joel%'
OR (Name LIKE '%good%' AND BookID=Books.CopyID AND KeywordID=Keywords.ID)
I thought using the brackets might separate the 2nd part into its own kinda clause, so the join was only evaluated in that part - but it doesn't seem to be so. All it gives me is a long list of multiple copies of the one book that satisfies the Title LIKE '%Joel%' bit.
Is there a way of doing this using pure SQL, or would I have to use two SQL statements and combine them in my app (removing duplicates in the process).
I'm using MySQL at the moment if that matters, but the app uses ODBC and I'm hoping to make it DB agnostic (might even use SQLite eventually or have it so the user can choose what DB to use).
You need to join the 3 tables together, which gives you a tablular resultset. You can then check any columns you like, and make sure you get distinct results (i.e. no duplicates).
Like this:
select distinct b.*
from books b
left join keywordslink kl on kl.bookid = b.bookid
left join keywords k on kl.keywordid = k.keywordid
where b.title like '%assd%'
or k.keyword like '%asdsad%'
You should also try to avoid starting your LIKE values with a percent sign (%), as this means SQL Server can't use an index on that column and has to perform a full (and slow) table scan. This starts to make your query into a "starts with" query.
Maybe consider the full-text search options in SQL Server, also.
What you've done here is made a cartesian result set by having the tables joined with the commas but not having any join criteria. Switch your statements to use outer join statements and that should allow you to reference the keywords. I don't know your schema, but maybe something like this would work:
SELECT
*
FROM
Books
LEFT OUTER JOIN KeywordsLink ON KeywordsLink.BookID = Books.CopyID
LEFT OUTER JOIN Keywords ON Keywords.ID = KeywordsLink.KeywordID
WHERE Books.Title LIKE '%JOEL%'
OR Keywords.Name LIKE '%GOOD%'
Use UNION.
(SELECT Books.* FROM <first kind of search>)
UNION
(SELECT Books.* FROM <second kind of search>)
The point is that you could write two (or more) simple and efficient queries instead of one complicated query that tries to do everything at once.
If number of resulting rows is low, then UNION will have very little overhead (and you can use faster UNION ALL if you don't have duplicates or don't care about them).
SELECT * FROM books WHERE title LIKE'%Joel%' OR bookid IN
(SELECT bookid FROM keywordslink WHERE keywordid IN
(SELECT id FROM keywords WHERE name LIKE '%good%'))
Beware that older versions of MySQL didn't like subselects. I think they've fixed that.
You must also limit the product of the join by specifying something like
Books.FK1 = Keywords.FK1 and
Books.FK2 = Keywordslink.FK2 and
Keywords.FK3 = Keywordslink.FK3
But i don't know your exact data model so your solution may be slightly different.
I'm not aware of any way to accomplish a "conditional join" in SQL. I think you'll be best served with executing the two statements separately and combining them in the application. This approach is also more likely to stay DB-agnostic.
It looks like Neil Barnwell has covered the answer that I would have given, but I'll add one thing...
Books can have more than one author. If your data model is really designed as your query implies you might want to consider changing it to accommodate that fact.