MYSQL Search for empty fields in table - mysql

I'm search through multiple tables.
SELECT DISTINCT cv.id, cv.tJobTitle, cv.tJobTitleAlt, cv.rEmployer, employee.firstName, employee.surname, cv.recentJobTitle, match ( cv.title, cv.recentJobTitle, cv.targetJobTitle, cv.targetJobTitleAlt ) AGAINST ('Desktop' IN BOOLEAN MODE) AS relevance
FROM cv AS cv, employee AS employee, country AS country
WHERE cv.showTo=1 AND cv.status=1 AND cv.employeeIDFK = employee.id AND cv.countryISO2FK='GB'
AND cv.countryISO2FK=country.iso2
AND match ( cv.title, cv.recentJobTitle, cv.targetJobTitle, cv.targetJobTitleAlt ) AGAINST ('Desktop' IN BOOLEAN MODE )
AND cv.salaryType='1' AND cv.salaryMax <=23088 OR cv.salaryMin is NUll
ORDER BY relevance DESC
I have a price values which I am search in my database but I also have a tick box to say if the price has not be set show that record.
So If the price field is empty then still show in result.
I have try the above but its giving me more the 100 records where my table only has 2 records.

Assuming country.iso2 is a unique field, I'm guessing that you multiple cv's per employee or vice-versa.
NOTE: It's good advice to avoid using the comman notation for INNER JOINs. Also, this will only work where your field3 is really empty and not NULL.

Related

mysql GROUP BY query showing partial matches in email field

I have the following query for finding duplicate email addresses in mysql db .
It's returning partial match duplicate values , how can get only exact matches ?
SELECT id, email, date FROM mytable GROUP BY email HAVING COUNT(email) > 1
For example its giving following results:
1234567890#foo.net
1234567890#bar.net
or
123#foo.com
456#foo.com
or
100abc#gmail.com
100xyz#foo.com
100xhsy#bar.com
#Abey I do this by joining the table into itself on the field I want to show is identical but where a truly unique value (like id) is different between the two records.
Here is how you would do that:
SELECT `mt1`.`id`,
`mt1`.`email`,
`mt1`.`date`
FROM `mytable` AS `mt1`
JOIN `mytable` AS `mt2` ON `mt2`.`email` = `mt1`.`email`
AND `mt2`.`id` <> `mt1`.`id`
GROUP BY `mt1`.`id`
If you want to have a distinct list of the duplicate emails and don't care to see each individual record, just trim out the other fields you are returning like this:
SELECT `mt1`.`email`
FROM `mytable` AS `mt1`
JOIN `mytable` AS `mt2` ON `mt2`.`email` = `mt1`.`email`
AND `mt2`.`id` <> `mt1`.`id`
GROUP BY `mt1`.`email`
Here is an example mocked up in sqlfiddle.
Hope this helps!

What is the proper MySQL way to take data from 4 rows, 1 column, and separate into 9 columns?

I've studied and tried days worth of SQL queries to find "something" that will work. I have a table, apj32_facileforms_subrecords, that uses 7 columns. All the data I want to display is in 1 column - "value". The "record" displays the number of the entry. The "title" is what I would like to appear in the header row, but that's not as important as "value" to display in 1 row based upon "record" number.
I've tried a lot of CONCAT and various Pivot queries, but nothing seems to do more than "get close" to what I'd like as the end result.
Here's a screen shot of the table:
The output "should" be linear, so that 1 row contains 9 columns:
Project; Zipcode; First Name; Last Name; Address; City; Phone; E-mail; Trade (in that order). And the values in the 9 columns come from "value" as they relate to the "record" number.
I know there are LOT of examples that are similar, but nothing I've found covers taking all the values from "value" and CONCAT to 1 row.
This works to get all the data I want - SELECT record,value FROM apj32_facileforms_subrecords WHERE (record IN (record,value)) ORDER BY record
But the values are still in multiple rows. I can play with that query to get just the values, but I'm still at a loss to get them into 1 row. I'll keep playing with that query to see if I can figure it out before one of the experts here shows me how simple it is to do that.
Any help would be appreciated.
Using SQL to flatten an EAV model representation into a relational representation can be somewhat convoluted, and not very efficient.
Two commonly used approaches are conditional aggregation and correlated subqueries in the SELECT list. Both approaches call out for careful indexing for suitable performance with large sets.
correlated subqueries example
Here's an example of the correlated subquery approach, to get one value of the "zipcode" attribute for some records
SELECT r.id
, ( SELECT v1.value
FROM `apj32_facileforms_subrecords` v1
WHERE v1.record = r.id
AND v1.name = 'zipcode'
ORDER BY v1.value LIMIT 0,1
) AS `Zipcode`
FROM ( SELECT 1 AS id ) r
Extending that, we repeat the correlated subquery, changing the attribute identifier ('firstname' in place of 'zipcode'. looks like we we could also reference it by element, e.g. v2.element = 2
SELECT r.id
, ( SELECT v1.value
FROM `apj32_facileforms_subrecords` v1
WHERE v1.record = r.id
AND v1.name = 'zipcode'
ORDER BY v1.value LIMIT 0,1
) AS `Zipcode`
, ( SELECT v2.value
FROM `apj32_facileforms_subrecords` v2
WHERE v2.record = r.id
AND v2.name = 'firstname'
ORDER BY v2.value LIMIT 0,1
) AS `First Name`
, ( SELECT v3.value
FROM `apj32_facileforms_subrecords` v3
WHERE v3.record = r.id
AND v3.name = 'lastname'
ORDER BY v3.value LIMIT 0,1
) AS `Last Name`
FROM ( SELECT 1 AS id UNION ALL SELECT 2 ) r
returns something like
id Zipcode First Name Last Name
-- ------- ---------- ---------
1 98228 David Bacon
2 98228 David Bacon
conditional aggregation approach example
We can use GROUP BY to collapse multiple rows into one row per entity, and use conditional tests in expressions to "pick out" attribute values with aggregate functions.
SELECT r.id
, MIN(IF(v.name = 'zipcode' ,v.value,NULL)) AS `Zip Code`
, MIN(IF(v.name = 'firstname' ,v.value,NULL)) AS `First Name`
, MIN(IF(v.name = 'lastname' ,v.value,NULL)) AS `Last Name`
FROM ( SELECT 1 AS id UNION ALL SELECT 2 ) r
LEFT
JOIN `apj32_facileforms_subrecords` v
ON v.record = r.id
GROUP
BY r.id
For more portable syntax, we can replace MySQL IF() function with more ANSI standard CASE expression, e.g.
, MIN(CASE v.name WHEN 'zipcode' THEN v.value END) AS `Zip Code`
Note that MySQL does not support SQL Server PIVOT syntax, or Oracle MODEL syntax, or Postgres CROSSTAB or FILTER syntax.
To extend either of these approaches to be dynamic, to return a resultset with a variable number of columns, and variety of column names ... that is not possible in the context of a single SQL statement. We could separately execute SQL statements to retrieve information, that would allow us to dynamically construct a SQL statement of a form show above, with an explicit set of columns to be returned.
The approaches outline above return a more traditional relational model, (individual columns each with a value).
non-relational munge of attributes and values into a single string
If we have some special delimiters, we could munge together a representation of the data using GROUP_CONCAT function
As a rudimentary example:
SELECT r.id
, GROUP_CONCAT(v.title,'=',v.value ORDER BY v.name) AS vals
FROM ( SELECT 1 AS id ) r
LEFT
JOIN `apj32_facileforms_subrecords` v
ON v.record = r.id
AND v.name in ('zipcode','firstname','lastname')
GROUP
BY r.id
To return two columns, something like
id vals
-- ---------------------------------------------------
1 First Name=David,Last Name=Bacon,Zip Code=98228
We need to be aware that the return from GROUP_CONCAT is limited to group_concat_max_len bytes. And here we have just squeezed the balloon, moving the problem to some later processing, to parse the resulting string. If we have any equal signs or commas that appear in the values, it's going to make a mess of parsing the result string. So we will have to properly escape any delimiters that appear in the data, so that GROUP_CONCAT expression is going to get more involved.

FULLTEX Search on two column of Different Table in Mysql

Can anyone help me to find the query for fulltext search?
I have two columns Product and Generic.
Table-Product:
1. ProductID (Integer)
2. GenericID (Integer)-FK
3. Product_Name (Varchar)
And in Table-Generic:
1. GenericID (Integer)
2. Generic_Name (Varchar)
What I need is to search the input string with the combined name of both Product_Name and Generic_Name.
my sample query is given below
SELECT
prod.ProductID AS ID,
generic.Generic_Name AS genericName,
prod.Product_Name AS packageName
FROM
Product prod
INNER JOIN
Generic generic ON prod.GenericID = generic.GenericID
WHERE
MATCH (prod.Product_Name ,generic.Generic_Name) AGAINST('+acb* +ace* +serr* +para*' IN BOOLEAN MODE)
ORDER BY prod.Product_Name ASC
It doesn't work because the columns are in different tables.
FULLTEXT search operations each use a FULLTEXT index. That index can only be on one table.
So, you could try using two fulltext search operations...
WHERE (
match(prod.Product_Name) against('+acb* +ace* +serr* +para*' in boolean mode)
OR
match(generic.Generic_Name) against('+acb* +ace* +serr* +para*' in boolean mode)
)
Or, for best performance and result-set ranking, you could build a new name table like this
GenericId NOT a primary key
IsGeneric 1 or 0
Name either Product_Name or Generic_Name
You would construct this table from the union of the names in your other two tables. For example, it might contain
4321 0 Advil
4321 0 Motrin
4321 1 Ibuprofen
4322 0 Coumadin
4322 1 Warfarin
Then, a query like this would do the trick
select prod.ProductID AS ID,
generic.Generic_Name AS genericName,
prod.Product_Name AS packageName
FROM Product prod
INNER JOIN Generic generic ON prod.GenericID = generic.GenericID
INNER JOIN Name ON Name.GenericID = prod.GenericID
WHERE MATCH(Name.Name) AGAINST('+acb* +ace* +serr* +para*' in boolean mode)
ORDER BY prod.Product_Name ASC
The second alternative is more work to program. But, because it puts both tradenames and generic names into a single fulltext index, it will be faster and it is likely to give better results.

Join 3 Tables Doesn't Return Correct Result

I have three tables and their structure are below.
In keyword table I have unique keywords. A keyword has more than one user or domain_id so I have keyword_user table.
In rank table I have some numbers related to keywords.
I want to return all keywords related with my selected domain_id.
My conditions are:
Must: return min(rank_position) from rank table
Must: rank.rank_date = keyword.keyword_last_date
Problem is:
If I write keyword_user.domain_id = 1234 it returns all rows from keyword table but rank results are incorrect.
If I write rank.domain_id it returns only rows that related with keyword_last_date normally.
using min(rank_position) on SELECT causing wrong results.
I want all keywords from keyword table where keyword_user.domain_id = XXX and rank_date = keyword.keyword_last_date. Domain must my domain id not anything else.
SELECT rank.rank_id
, keyword_name
, keyword_last_date
, MIN(rank_position) my_rank
, rank_url
, rank.domain_id
FROM keyword
LEFT
JOIN keyword_user
ON keyword.keyword_id = keyword_user.keyword_id
LEFT
JOIN rank
ON keyword.keyword_id = rank.keyword_id
WHERE keyword_user.domain_id = 8262
AND rank.domain_id = 8262
AND rank_date = keyword.keyword_last_date
GROUP
BY keyword.keyword_name
ORDER
BY rakip_rank
As you can see from picture. domain_id column has different values but I have domain_id = 8262. They are not related to my expected result. Also my_rank column should different values not only "1".
TABLE: keyword
TABLE: rank
TABLE: keyword_user

Mysql fulltext index search returning weird result

I have ingredient table. I want all those recipes which have certain ingredients. Below is my table structure.
Table(ingredient) - Applied fulltext index on ingredient column.
------------------------------------------------------
ingredientID rcteID ingredient
310 1 Mint Leaves
311 1 Corriender Leaves
312 1 GreenChili
I am trying to fetch above record below fulltext search query but not getting that record.
SELECT `Ingredient`.`ingredientID` , `Ingredient`.`rcteID`
FROM `ingredient` AS `Ingredient`
WHERE MATCH (`Ingredient`.`ingredient`)
AGAINST ('+Mint Leaves +Corriender Leaves +Greenchili' IN BOOLEAN MODE)
AND `Ingredient`.`rcteID`
IN ( 1 )
GROUP BY `Ingredient`.`rcteID`
Why above query is not working for above record?
When I tried below query it worked. just changed searching text.
SELECT `Ingredient`.`ingredientID` , `Ingredient`.`rcteID`
FROM `ingredient` AS `Ingredient`
WHERE MATCH (`Ingredient`.`ingredient`)
AGAINST ('+Greenchili +Mint Leaves +Corriender Leaves' IN BOOLEAN MODE)
AND `Ingredient`.`rcteID`
IN ( 1 )
GROUP BY `Ingredient`.`rcteID`
OUTPUT
--------------------
ingredientID rcteID
311 1
Don't understand what's going on. Why first query not returning any result and below query returning result?
This is not an real explanation, but you can run this query to see the score.
SELECT MATCH (`Ingredient`.`ingredient`)
AGAINST ('+Mint Leaves +Corriender Leaves +Greenchili' IN BOOLEAN MODE)
FROM `ingredient` AS `Ingredient`
WHERE MATCH (`Ingredient`.`ingredient`)
AGAINST ('+Mint Leaves +Corriender Leaves +Greenchili' IN BOOLEAN MODE)
I believe that your query mean: find ingredients that each of them contains ALL of these Mint Leaves, Corriender Leaves, Greenchili, and which is not found in your data set. MySQL cannot find any row that contains all of these keywords above.
However if you but your query into brackets, it is a different story:
SELECT `Ingredient`.`ingredientID` , `Ingredient`.`rcteID`
FROM `ingredient` AS `Ingredient`
WHERE MATCH (`Ingredient`.`ingredient`)
AGAINST ('(+Greenchili) (+Mint Leaves) (+Corriender Leaves)' IN BOOLEAN MODE)
AND `Ingredient`.`rcteID`
IN ( 1 )
GROUP BY `Ingredient`.`rcteID`
This query can be translated into: Fetch me ingredients which contains AT LEAST one of these:Mint Leaves, Corriender Leaves, Greenchili and group them by rcteID.
UPDATED:
SELECT t1.rcteID FROM `ingredient` t1
JOIN `ingredient` t2 ON t2.rcteID = t1.rcteID
JOIN `ingredient` t3 ON t3.rcteID = t2.rcteID
WHERE
MATCH (t1.`ingredient`) AGAINST ('+Greenchili' IN BOOLEAN MODE)
AND
MATCH (t2.`ingredient`) AGAINST ('+Mint Leaves' IN BOOLEAN MODE)
AND
MATCH (t3.`ingredient`) AGAINST ('+Corriender Leaves' IN BOOLEAN MODE)
AND t1.`rcteID` IN ( 1 )
GROUP BY t1.`rcteID`
I think this query will work for you. Basically, it share the same idea with you but it looks for 3 keywords separately and only get the rcteID which contains 3 ingredients.