SQL Searching Part of a Sentence in Two Fields Simultaniously - php

In my MSSQL table I have two fields, first one is post_name (position at job) and another filed is org_name (names or location of organizations). I'm writting a PHP script to seach through those two fields. I use Select2 Bootstrap plugin which is basically a seach line with dropdown options fetched from the database based on what user is typing in.
A user usually search for full job title including post_name and org_name. Let's say "Chief Sales Manager Toronto" where first 3 words are from first field and the last word is from second field. When a user start typing Chief Sales Man..." he should be alble to get the whole list of such managers in Toronto, Cupertino or whatever.
The SELECT query I use for this is:
SELECT post_name, org_name
FROM table
WHERE post_name LIKE 'searchTerm%';
That gives me the needed job titles only if I didn't start typing the org name as obviously then it tries to find the whole sentence in post_name filed and gives an empty string.
I also tried:
SELECT post_name, org_name
FROM table
WHERE post_name LIKE 'searchTerm%' OR org_name LIKE '%searchTerm%';
or I was trying to split the searchTerm and try to seach in org_name field by using end of searchTerm:
SELECT post_name, org_name
FROM table
WHERE post_name LIKE 'searchTerm%'
AND org_name LIKE '%.substr(searchTerm, -6).%';
But the last ones are even more pathetic. I was thinking of using CONCAT to unite those two fields so I can search in those two as one, something like
SELECT CONCAT(post_name, org_name) as full_title
FROM table
WHERE full_title LIKE 'searchTerm%';
But in MSSQL Server Express 2005 I get an error of non existing function.
Is there any way I could search such a one sentence in those two fields simultaniously?

The query you want in SQL Server seems to be:
SELECT post_name, org_name
FROM table
WHERE post_name + org_name LIKE 'searchTerm%';
You might want to include a space between the columns as well.
That said, you might want to look into full text search capabilities. It might be a better solution to your problem.

Your last query would work like this
SELECT post_name, org_name
FROM (
SELECT post_name, org_name,
CONCAT(post_name,' ', org_name) as full_title
FROM table
) z
WHERE full_title LIKE 'searchTerm%';

Related

SQL Query: Get String with highest number | Parse?

I have a database which looks like this:
Do not ask my why, but this is written by a WordPress plugin so I have to handle with it. What I want is to get every link where the meta_key = product_shops_X_link. But every post has a variable amount of product shop links.
In this picture I tried Where meta_key Like "%_link%". But if I do a query like that I also get all meta_keys where the product_shops_X_link field has a _ before the product...
What I want is just all product_shops_X_link fields. Now there a two ways I think.
Way 1: Get the highest number of the meta key fields Where meta_key Like "%product_shops_X_link%" OR meta_key Like "%_product_shops_X_link%". It doesn't matter of _product or just product. The numbers are equal. If there is just a product_shops_0_link field there must be also a _product_shops_0_link field.
Way2: Create a pattern which only searches for all product_shops_X_link fields without the beginning of _product and give me ALL product_shops_X_link fields. Whatever number is contained in the field.
But in both cases I do not know how to code that..
Does anyone knows how to code that or is there maybe a better way?
Greetings and Thank You!
If you don't want entries starting with _product then you can exclude _ or % from your LIKE pattern, e.g.:
SELECT *
FROM links
WHERE meta_key LIKE 'product_%';
But how can I add some more attributes to the query like post_id or
meta_key
Those can be combined with AND, for example to query items with post_id = 21179 and meta_key starts with product_..:
SELECT myFields
FROM myTable
WHERE (post_id = 21179) AND (meta_key LIKE 'product_shops_%')
Sorry if I am misunderstanding but are you trying to capture the number from those rows? If so, you can use the native REPLACE() function like this:
SELECT *, REPLACE(REPLACE(meta_key, 'product_shops_', ''),'_link','') as captured_number
FROM mytable
WHERE meta_key LIKE 'product\_shops\_%\_link'
ORDER BY captured_number DESC
This will get you the rows you want with the highest number first. Alternately you can use this regex library for mysql and then use regex to capture the number:
SELECT *, PREG_CAPTURE( '/product_shops_([0-9]+)/', meta_key) as captured_number
FROM mytable
WHERE meta_key LIKE 'product\_shops\_%\_link'
ORDER BY captured_number DESC

MySQL Group Identical titles (row) and sum the money(row) but keep individual timestamp for sorting

I have been all over the internet to find answer for this, but I can't find any. (I might be asking incorrectly?)
I have a table which looks like this:
I have been using the query:
SELECT title, date, SUM(money)
FROM payments
WHERE username = '$username_n' and type=0
GROUP BY title
It does the trick, and it groups the identical titles and sum up their values
But as you can see, it only gives me ONE date, and I would like to be able to make a slider, where I can sort the date from the date, but I can't do that if it creates only one date for each grouped title.
How can I create multiple dates, but still get rid of the duplicated titles?
Try this:
SELECT title, date, SUM(money) FROM payments
WHERE username = '$username_n' and type=0 GROUP BY title, date(`date`);
It is a little weird with fields in the field list that are not aggregated or part of the grouping. As you had before with the date field:
SELECT title, date, SUM(money) FROM payments
WHERE username = '$username_n' and type=0
GROUP BY title
You group by title, and aggregate the money field, all good. The date field is not part of grouping or aggregation. What mysql is doing, it will just take the field value for the date field in the aggregation. Thats why you only see one date value in your result. As code-monk explained you need to use date field in the grouping. In MS SQL Server your query would actually error our, as MS SQL Server doesnt allow fields that are not part of grouping or aggregated, which I think is very good.
Below query will give date values in comma separated manner. You can use PHP/server side code to explode those by comma and create a list/array and return it to client side i.e. JavaScript. Use javascript to sort the list.
SELECT title, group_concat(date) as `dates`, SUM(money)
FROM payments
WHERE username = '$username_n' and type=0
GROUP BY title

Getting most relevant results when searching from multiple tables (php, mysql)

I am searching from 3 tables currently (will search in more after sorting this out). This query brings all the results in the order of the tables listed in query. Whereas I want to get the most relevant search results first.
(Select name, url, text, 'behandlinger_scat' AS `table` from behandlinger_scat where name LIKE '%KEYWORD%' OR text LIKE '%KEYWORD%')
UNION
(Select name, url, text, 'hudsykdommer_scat' AS `table` from hudsykdommer_scat where name LIKE '%KEYWORD%' OR text LIKE '%KEYWORD%')
UNION
(Select name, url, text, 'om_oss' AS `table` from om_oss where name LIKE '%KEYWORD%' OR text LIKE '%KEYWORD%')
Any help would be appreciated.
You can use a method to order by the points you dynamically give the results, as in this example (you will need to alias your tables so SQL will understand what column you're referring to):
ORDER BY
CASE WHEN name LIKE table.keywords THEN 100 ELSE 0 END +
CASE WHEN name LIKE table2.keywords THEN 10 ELSE 0 END +
CASE WHEN text LIKE table2.keyword THEN 1 ELSE 0 END
DESC
This is merely an example, but the concept is the following:
You decide how many "points" each "match" will receive (e.g name matches keyword is 100 points, text matches it - a little less) then, each row "accumulates" points with correlation to its matches, and the row with the most points shows first.

MSQL query for displaying results based on the same keywords

I have a table called cakes that contains the columns: id, title, description, keywords. I also have a table called keywords, with cakes being the parent. The keywords table contains two columns: id and keyword
I need two queries: UPDATED
If a person types in ingredients such as chocolate, hazelnut, strawberry (could be anything separated by a comma) I need the query to search for cakes that contain all three keywords and display results. Display ONLY cakes that contain all three. If no cake matches, I need a message saying nothing found.
I have a label on the search box which says, Find similar cakes. If a person types in Vanilla Raspberry or example, the query needs to locate the cake in the database and match its keywords to the keywords of other cakes and display results. Display ONLY cakes that have the same keywords.
Not sure how to write these queries. Any help is appreciated. Thanks!
If the database must use a delimited long-string field for "keywords" rather than putting them in rows, then you will want to use the LIKE Operator
Assuming your [keywords] column is formatted like this:
'chocolate,ganache,strawberry'
You can search for "similar" cakes like this:
SELECT
columns
FROM
table t
WHERE
t.[keywords] LIKE '%chocolate%'
OR t.[keywords] LIKE '%cheesecake%'
Though, if you can change the schema, I would do so. Searching normalized keyword rows will be much more efficient and fast than having the DB parse through text using LIKE
If you could make a keywords table, which references the parent table by ID, you could do an equality search using a JOIN which would be superior, in my opinion.
It might have three columns: Id, ParentId, Keyword
EDIT: So based on your update, you have a cakewords table which can be searched.
This is untested, and there is likely a more efficient way using no IN clause. But the idea is that you know all the keyword id's for your specific cake. Then you are looking for other cakes having keywords in that collection.
SELECT
columns
FROM
cake AS cs
JOIN
cakewords AS csw
ON csw.[cakeid] = cs.[id]
WHERE
csw.[wordid] IN
(SELECT
cw.[wordid]
FROM
cakewords AS cw
JOIN
cakes AS c
ON c.[id] = cw.[cakeid]
WHERE
c.[id] = #pMyCurrenctCakeId
(
EDIT2: Here is a good related question:
What's the optimal solution for tag/keyword matching?
Based on an answer within, you might try this:
SELECT DISTINCT
c.[id]
FROM
cakewords AS cw1
INNER JOIN cakewords cw2
ON cw2.[wordid] = cw1.[wordid]
INNER JOIN cake AS c
ON c.[id] = cw.[cakeid]
WHERE
cw1.[cakeid] = #current_cake_id

Mysql Unique Query

I have a programme listing database with all the information needed for one programme packed into one table (I should have split programmes and episodes into their own) Now since there are multiple episodes for any given show I wish to display the main page with just the title names in ascending and chosen letter. Now I know how to do the basic query but this is all i know
SELECT DISTINCT title FROM programme_table WHERE title LIKE '$letter%'
I know that works i use it. But I am using a dynamic image loading that requires a series number to return that image full so how do I get the title to be distinct but also load the series number from that title?
I hope I have been clear.
Thanks for any help
Paul
You can substitute the DISTINCT keyword for a GROUP BY clause.
SELECT
title
, series_number
FROM
programme_table
WHERE title LIKE '$letter%'
GROUP BY
title
, series_number
There are currently two other valid options:
The option suggested by Mohammad is to use a HAVING clause in stead of the WHERE clause this is actually less optimal:
The WHERE clause is used to restrict records, and is also used by the query optimizer to determine which indexes and tables to use. HAVING is a "filter" on the final result set, and is applied after ORDER BY and GROUP BY, so MySQL cannot use it to optimize the query.
So HAVING is a lot less optimal and you should only use it when you cannot use 'WHERE' to get your results.
quosoo points out that the DISTINCT keyword is valid for all listed columns in the query. This is true, but generally people do not recommend it (there is no performance difference *In some specific cases there is a performance difference***)**. The MySQL optimizer however spits out the same query for both so there is no actual performance difference.
Update
Although MySQL does apply the same optimization to both queries, there is actually a difference: when DISTINCT is used in combination with a LIMIT clause, MySQL stops as soon as it finds enough unique rows. so
SELECT DISTINCT
title
, series_number
FROM
programme_table
WHERE
title LIKE '$letter%'
is actually the best option.
select title,series_number from programme_table group by title,series_number having title like '$letter%';
DISTINCT keyword works actually for a list of colums so if you just add the series to your query it should return a set of unique title, series combinations:
SELECT DISTINCT title, series FROM programme_table WHERE title LIKE '$letter%'
Hey thanks for that but i have about 1000 entries with the same series so it would single out the series as well rendering about 999 programmes useless and donot show.
I however found out away to make it unique and show the series number
SELECT * FROM four a INNER JOIN (SELECT title, MIN(series) AS MinPid FROM four WHERE title LIKE '$letter%' GROUP BY title) b ON a.title = b.title AND a.series = b.MinPid
Hopefully it helps anyone in the future and thank you for the replies :)

Categories