mysql multi-table fulltext query problem? - php

I am making a multi-table fulltext query.But I met some question.
I need make a query like
(SELECT
title,content,date,cat
FROM article1
WHERE
cat='Science fiction'
AND
MATCH (title,content)
AGAINST
('+Harry +Potter' IN BOOLEAN MODE))
UNION
(SELECT
title,content,date
FROM article3
WHERE MATCH (title,content)
AGAINST
('+Harry +Potter' IN BOOLEAN MODE))
Order By date DESC LIMIT 10
But it caused Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource
If I deleted cat='Science fiction' AND it can pass the test.
Where is the problem? If I want make a query what I want: first fulltext query require need meet cat='Science fiction'. Thanks a lot.

You are trying to UNION together result sets that return a different number of columns. Your first query returns 4 columns (title,content,date,cat) while your second only returns 3 (title,content,date). Each query must return the same number of columns.

I don't know why removing the cat LIKE 'Science fiction' makes the query work. As written, it should not work in either case. UNION requires both parts of the queries to produce the same number of columns with compatible types. Your UNION has 4 columns in the first part and 3 columns in the second:
SELECT title, content, date, cat FROM article1
UNION
SELECT title, content, date FROM article3

Did mysql_query return FALSE, indicating a problem parsing your query? If you blindly passed "FALSE" into mysql_fetch_array(), I'd expect to see that kind of error.

try
cat LIKE 'Science fiction'

Related

Show Orderby Array value Value in SQL Query When using IN() [duplicate]

I have a PHP array with numbers of ID's in it. These numbers are already ordered.
Now i would like to get my result via the IN() method, to get all of the ID's.
However, these ID's should be ordered like in the IN method.
For example:
IN(4,7,3,8,9)
Should give a result like:
4 - Article 4
7 - Article 7
3 - Article 3
8 - Article 8
9 - Article 9
Any suggestions? Maybe there is a function to do this?
Thanks!
I think you may be looking for function FIELD -- while normally thought of as a string function, it works fine for numbers, too!
ORDER BY FIELD(field_name, 3,2,5,7,8,1)
You could use FIELD():
ORDER BY FIELD(id, 3,2,5,7,8,1)
Returns the index (position) of str in the str1, str2, str3, ... list. Returns 0 if str is not found.
It's kind of an ugly hack though, so really only use it if you have no other choice. Sorting the output in your app may be better.
Standard SQL does not provide a way to do this (MySQL may, but I prefer solutions that are vendor-neutral so I can switch DBMS' at any time).
This is something you should do in post-processing after the result set is returned. SQL can only return them in an order specified in the "order by" clause (or in any order if there's no such clause).
The other possibility (though I don't like it, I'm honor-bound to give you the choice) is to make multiple trips to the database, one for each ID, and process them as they come in:
select * from tbl where article_id = 4;
// Process those.
select * from tbl where article_id = 7;
// Process those.
: : : : :
select * from tbl where article_id = 9;
// Process those.
You'll just need to give the correct order by statement.
SELECT ID FROM myTable WHERE ID IN(1,2,3,4) ORDER BY ID
Why would you want to get your data ordered unordered like in your example?
If you don't mind concatening long queries, try that way:
SELECT ID FROM myTable WHERE ID=1
UNION
SELECT ID FROM myTable WHERE ID=3
UNION
SELECT ID FROM myTable WHERE ID=2

Can you combine a simple MYSQL Statement with a FullText Statement

I've built an internal DB / Search Engine for art creatives. I'm trying to create a search criterion where you can query one column in the database and also search several columns in the database for a phrase search using FullText Search. The example of a search query might be: November {and} Black Friday. November would search for creatives matching the created_for column and the black friday would search headline, subheadline and additional_text columns with a fulltext search. Any ideas of how to accomplish this would be really helpful!
SELECT
(SELECT * FROM headlines WHERE created_for = '$searchString' AND image_slug <> '')
(SELECT *, MATCH(headline) AGAINST('$fullText' IN BOOLEAN MODE) AS MultiScore, MATCH(subheadline, additional_text) AGAINST('$fullText' IN BOOLEAN MODE) AS MultiSecondScore
FROM `headlines`
WHERE MATCH(headline, subheadline, additional_text) AGAINST('$fullText' IN BOOLEAN MODE))
I've tried adding a UNION statement before the second Select statement, but I get an error message saying the columns don't match. Not sure what I've got wrong here, but thanks in advance for your help!
Use AND in the WHERE clause.
SELECT *, MATCH(headline) AGAINST('$fullText' IN BOOLEAN MODE) AS MultiScore, MATCH(subheadline, additional_text) AGAINST('$fullText' IN BOOLEAN MODE) AS MultiSecondScore
FROM headlines
WHERE created_for = '$searchString'
AND image_slug <> ''
AND MATCH(headline, subheadline, additional_text) AGAINST('$fullText' IN BOOLEAN MODE)
UNION would get results that match either of the criteria, not both of them. And when you use UNION, both subqueries have to return the same number of columns -- you would have to add extra columns to the first query to match the MultiScore and MultiSecondScore columns of the first query.

PHP + Mysql complicated SQL SELECT query

I was thought how to make a complicated (as I think) SELECT query from table with 3 kind of comments (first - positive comments, second - negative comments and third - neutral comments). Using PHP I would like to SELECT and diplay first negative comments, and right after negative comments diplay all other type of comments. How to diplay them with one SELECT query together with LIMIT that I use to separate for pagination?
Example of table:
id - unique id
type - (value 1-positive, 2-negative, 3-neutral)
text - value
I was thought first SELECT * FROM comments WHERE type='2' ORDER BY id LIMIT 0,100
while(){
...
}
Right after that second
SELECT * FROM commetns WHERE type!='2' ORDER BY id LIMIT 0,100
while(){
...
}
But how use LIMIT for pagination if there is two different SELECT queries?
Use a combination of UNION and LIMIT.
However, you need to determine the bind variables, and specify the number of rows you want to display.
(SELECT * FROM comments WHERE type = '2' LIMIT ?)
UNION
(SELECT * FROM comments WHERE type != '2' LIMIT ?);
SQLFiddle: http://sqlfiddle.com/#!9/6d682/1
Use an IF statement in the ORDER BY clause to change the type 2 to sort first:-
SELECT *
FROM comments
ORDER BY IF(type = 2, 0, type)
LIMIT 1, 20
This will give you all the negative (type 2) comments first, followed by the other comments (whether positive or neutral). You would probably want to add an extra column to the sort just for consistency of display.
I didn't get your case exactly, but I think you may use OR operator to get what you want:
SELECT * from comments WHERE type=2 OR type=-2 ORDER BY type DESC
you can use union to merge group of tables, but you must have the same columns in all the tables, for example:
select commetns,'nagtive' as type from nagtive_tbl limit 10
union
select commetns,'positive' as type from positive_tbl limit 10
union
select commetns,'neutral' as type from neutral_tbl limit 10
this query return table with all the comments from different tables each row contain is type so you can filter it while you building the lists on the client.
I must be missing context, otherwise you would just be fine using:
SELECT * from comments ORDER BY type ASC LIMIT 0,10
So by ordering the type, you'll first get all the items with type 1, followed by 2 and 3.
Just using the limit will chop them in the pieces you want and it will still respect the order.

MySQL UTF-8 Full Text Search with multiple bound parameters

My query shows like that:
SELECT advert_id
FROM oop_adverts
WHERE cat_down = :id
AND province = :province
AND MATCH (location) AGAINST (:location);
in practise:
SELECT advert_id
FROM oop_adverts
WHERE cat_down = 3
AND province = 5
AND MATCH (location) AGAINST ('Krakow');
And if I try this query, mysql finally get 0 results.
The problem is polish phrases in query. When I replaced this query for:
SELECT advert_id
FROM oop_adverts
WHERE cat_down = 3
AND province = 5
AND MATCH (location) AGAINST ('Krakow') COLLATE utf8_unicode_ci;`
I got:
Syntax error or access violation: 1253 COLLATION 'utf8_unicode_ci' is not valid for CHARACTER SET 'binary''
I don't know what collate I should use in script php and in mysql. Can you help me?
PS. Sorry for my "best english" bro.
What's the table schema?
I guess 'location' is defined as a binary string and cannot be compared using a collation like utf8_unicode_ci.
Give a read here for more info.
http://dev.mysql.com/doc/refman/5.0/en/charset-binary-collations.html
Edit:
Tell us your schema for further help. However try something like this:
SELECT advert_id
FROM oop_adverts
WHERE cat_down = 3
AND province = 5
AND MATCH (CONVERT(BINARY(location) USING utf8)) AGAINST ('Krakow');
EDITED as per discussion in comments:
As your table scheme looks fine (in terms of utf8) and the first code example you gave in OP is correct (the one without collate), assuming you've got the proper DB collation and the connection itself as well - most probably you have Kraków for advert_location in more than 50% of rows and that is why you get 0 rows of result.
If you want to user Full Text Search, you have to always remember that if a table's fulltext index contains a keyword that appears in 50% of the data rows, that keyword will be ignored by the match query.
So instead you can use Full Text Serach in boolean mode to bypass the 50% threshold. Check the docs here MySQL Boolean Full-Text Searches
So for example, if you have 3 rows in table with Kraków, Krakow and Warszawa as advert_location, the below query will give you 0 rows result:
SELECT advert_id
FROM oop_adverts
WHERE MATCH(`advert_location`) AGAINST ('Kraków')
But if you use the boolean mode, you will get 2 rows result:
SELECT advert_id
FROM oop_adverts
WHERE MATCH(`advert_location`) AGAINST ('Kraków' IN BOOLEAN MODE)
If you wish to match multiple words, you can use the "+" operator (refer to the docs linked above for details).
SELECT advert_id
FROM oop_adverts
WHERE MATCH(`advert_location`,`advert_title`) AGAINST ('+Kraków' '+Search phrase' IN BOOLEAN MODE)
One remark, remember to construct the bound parameter already with the "+" operator included, for example if you are using PHP you can do like this:
$query= "SELECT advert_id
FROM oop_adverts
WHERE MATCH(`advert_location`,`advert_title`) AGAINST (:location :title IN BOOLEAN MODE)";
$SQL=$db->prepare($query);
$SQL->bindValue(':location', '+'.$searched_location, PDO::PARAM_STR);
$SQL->bindValue(':title', '+'.$searched_title, PDO::PARAM_STR);

MySQL Benchmark

I am trying to use MySQL benchmark to test some queries. But, I am running to an error.
SELECT benchmark (10000, (select title from user));
and in return I get this error;
ERROR 1242 (21000): Subquery returns more than 1 row
Does anyone know how to benchmark a query?
Thanks
select title from user
This returns multiple rows, which won't work.
Refer to this link:
http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_benchmark
The expression you pass must return a scalar result.
You need to change the query such that it returns a single row:
ex:
select title from user where user_name = 'some_user'
you can use the mysqlslap utility to benchmark queries, see:
http://dev.mysql.com/doc/refman/5.1/en/mysqlslap.html
From http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_benchmark
Only scalar expressions can be used.
Although the expression can be a
subquery, it must return a single
column and at most a single row. For
example, BENCHMARK(10, (SELECT * FROM
t)) will fail if the table t has more
than one column or more than one row.
Try
SELECT BENCHMARK(10000, (SELECT title FROM user LIMIT 1));

Categories