I have 5 fields of "keywords" that have been assigned to each record.
I'd like to build a query that will select and identify only those records sharing a common keyword.
So it would be like "show me records than have the keyword "environment" in any of the 5 fields it may say so."
I'm pretty new at this and am a little frustrated.
Thanks for all the help!
SELECT
* -- or whatever fields you need
FROM tablename
WHERE
keyword1='environment' -- maybe keyword1 LIKE '%environment%'
OR keyword2='environment'
OR keyword3='environment'
OR keyword4='environment'
OR keyword5='environment'
That said, you should reconsider your DB structure: The canonical way to do this, is to have your table, a keyword table and a jointable:
Your table has an ID
The keyword table has the keyword and an ID
The jointable has yourtable.ID and keywords.ID
This way you can
attach an arbitrary count of keywords to your records
keep your keywords consitent ("Theater" vs. "Theatre")
have a foot in the door for keyword internationalization
get rid of the query we started with: It now reads
.
SELECT
yourtable.*
FROM yourtable
INNER JOIN yourtable_keywords ON yourtable.ID is yourtable_keywords.yourtableID
INNER JOIN keywords ON keywords.ID is yourtable_keywords.keywordID
WHERE keywords.keyword='environment'
Related
I'm trying to learn SQL queries, and I've encountered things like this:
SELECT name FROM customer_list t
WHERE ...
What does the t mean? Is it like the name of an instance of that table?
Thanks!
The t is an alias that you can refer to instead of the table name in your query. If you have only one table you're querying from it isn't very useful, but it comes in hand when you have multiple tables (e.g., in join clauses and you want to avoid writing the entire long table name whenever you refer to it. E.g.:
SELECT t.name
FROM some_long_table_name t
JOIN some_other_long_table_name s ON t.id = s.id
I would like to JOIN 2 databases.
1 database is keyword_data (keyword mapping)
1 database is filled with Google rankings and other metrics
Somehow I cannot JOIN these two databases.
Some context:
DATA SET NAME: visibility
TABLE 1
keyword_data
VALUES
keyword
universe
category
search_volume
cpc
DATA SET NAME: visibility
TABLE 2
results
VALUES
Date
Keyword
Website
Position
In order to receive ranking data by date I wrote the following SQL line.
SELECT Date, Position, Website FROM `visibility.results` Keyword INNER
JOIN `visibility.keyword_data` keyword ON `visibility.results` Keyword
= `visibility.keyword_data` keyword GROUP BY Date;
(besides that, 100 other lines with no success ;-) )
I am using Google BigQuery for this with standard SQL (unchecked Legacy SQL).
How can I JOIN those 2 data tables?
How familiar are you with SQL? I think you're using aliases wrong, something like this should work
SELECT r.Date, r.Position, r.Website
FROM `visibility.results` AS r
INNER JOIN `visibility.keyword_data` AS k
ON r.Keyword = k.keyword
GROUP BY DATE
First of all i have never worked with Google big query but there is a couple of things wrong in my opinion with this query.
To start with you join tables by including the name of the table then you provide the key that the tables are joined by. Also if you don't use aggregate functions (MIN/MAX etc.) in your select statement you must include all values in the group by clause as well. In reference I can provide you a solution that would work if you would of used Microsoft SQL Server if that would be of any help because if you reference here the syntax is quite similar.
SELECT results.Date AS DATE,
,results.Position AS POSITION
,results.Website AS WEBSITE
FROM visibility.dbo.keyword_data AS keyword_data
INNER JOIN visibility.dbo.results AS results
ON results.keyword = keyword_data.keyword
GROUP BY results.Date
,results.Position
,results.Website
I have a table "mytable" contains several columns including one called "ip." There is another table called "bots" with only one column "bot", which is a list of several ip address values. I want to filter out all rows in mytable with "ip" value in table bots.
I wrote
select * from mytable
where ip not in (select bot from bots);
Apparently this is not the way to do it. I am wondering what is the correct syntax.
I googled around but the keywords here "where" and "in" are too common in the English language and hence hard to find any useful results.
select mytable.* from
mytable left outer join bots on mytable.id = bots.bot
where bots.bot is null
I have 6 tables, let's call them a,b,c,d,e,f. Now I want to search all the colums (except the ID columns) of all tables for a certain word, let's say 'Joe'. What I did was, I made INNER JOINS over all the tables and then used LIKE to search the columns.
INNER JOIN
...
ON
INNER JOIN
...
ON.......etc.
WHERE a.firstname
~* 'Joe'
OR a.lastname
~* 'Joe'
OR b.favorite_food
~* 'Joe'
OR c.job
~* 'Joe'.......etc.
The results are correct, I get all the colums I was looking for. But I also get some kind of cartesian product, I get 2 or more lines with almost the same results.
How can i avoid this? I want so have each line only once, since the results should appear on a web search.
UPDATE
I first tried to figure out if the SELECT DISTINCT thing would work by using this statement: pastie.org/970959 But it still gives me a cartesian product. What's wrong with this?
try SELECT DISTINCT?
On what condition do you JOIN this tables? Do you have foreign keys or something?
Maybe you should find that word on each table separately?
What kind of server are you using? Microsoft SQL Server has a full-text index feature (I think others have something like this too) which lets you search for keywords in a much less resource-intensive way.
Also consider using UNION instead of joining the tables.
Without seeing your tables, I can only really assume what's going on here is you have a one-to-many relationship somewhere. You probably want to do everything in a subquery, select out the distinct IDs, then get the data you want to display by ID. Something like:
SELECT a.*, b.*
FROM (SELECT DISTINCT a.ID
FROM ...
INNER JOIN ...
INNER JOIN ...
WHERE ...) x
INNER JOIN a ON x.ID = a.ID
INNER JOIN b ON x.ID = b.ID
A couple of things to note, however:
This is going to be sloooow and you probably want to use full-text search instead (if your RDBMS supports it).
It may be faster to search each table separately rather than to join everything in a Cartesian product first and then filter with ORs.
If your tables are entity type tables, for example a being persons and b being companies, I don't think you can avoid a cartesian product if you search for the results in this way (single query).
You say you want to search all the tables for a certain word, but you probably want to separate the results into the corresponding types. Right? Otherwise a web search would not make much sense.
So if you seach for 'Joe', you want to see persons containing the name 'Joe' and for example the company named 'Joe's gym'. Since you are searching for different entities so you should split the search into different queries.
If you really want to do this in one query, you will have to change your database structure to accommodate. You will need some form of 'search table' containing an entity ID (PK) and entity type, and a list of keywords you want that entity to be found with. For example:
EntityType, EntityID, Keywords
------------------------------
Person, 4, 'Joe', 'Doe'
Company, 12, 'Joe''s Gym', 'Gym'
Something like that?
However it's different when your search returns only one type of entity, say a Person, and you want to return the Persons for which you get a hit on that keyword (in any related table to that Person). Then you will need to select all the fields you want to show and group by them, leaving out the fields in which you are searching. Including them inevitably leads to a cartesian product.
I'm just brainstorming here, by the way. It hope it's helpful.
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.