full-text search 2 tables - php

I have two tables. One stores video information, the other stores the tags associated with that video. They share the common field vid_id. I am trying to fulltext search both tables for matches. The goal is that if there is a match in either table, then all fields with that vid_id be gathered from video.
The problem is my query just crashes with Call to undefined method PDOConnectionFactory::errorInfo(). It should return one row since there is one entry in tags where name field = test. Anyone have any ideas? I have been struggling with this for a while.
CREATE TABLE IF NOT EXISTS `tags` (
`id` varchar(35) NOT NULL,
`vid_id` varchar(35) NOT NULL,
`name` varchar(45) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
UNIQUE KEY `vid_id` (`vid_id`,`name`),
FULLTEXT KEY `name` (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS `video` (
`timestamp` int(11) NOT NULL,
`vid_id` varchar(32) NOT NULL,
`file_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`uploader` varchar(55) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`title` varchar(30) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`subject_id` int(1) NOT NULL,
FULLTEXT KEY `title` (`title`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
$sql = "SELECT video.*
MATCH(video.title) AGAINST('?') as cscore,
MATCH(tags.name) AGAINST('?') as htscore
FROM video
LEFT JOIN tags ON video.vid_id=tags.vid_id
WHERE
MATCH(video.title) AGAINST('?') OR
MATCH(tags.name) AGAINST('?')
ORDER BY cscore DESC;";
$stmt4 = $conn->prepare($sql);
$result=$stmt4->execute(array('test','test','test','test')) or die(print_r($db->errorInfo(), true));

The problem is that you're missing a comma (,) after SELECT video.* in your SQL query.
Working example:
SELECT video.*,
MATCH(video.title) AGAINST('?') as cscore,
MATCH(tags.name) AGAINST('?') as htscore
FROM video
LEFT JOIN tags ON video.vid_id=tags.vid_id
WHERE
MATCH(video.title) AGAINST('?') OR
MATCH(tags.name) AGAINST('?')
ORDER BY cscore DESC;

Related

MySQL MATCH AGAINST JOIN issue

I'm making a PHP + MySQL app for company records management and I need an joint result from several tables based on fulltext search in every table.
The query is formed dynamically and in worst case looks so:
SELECT `contracts_info`.`contract_number`, `contracts_info`.`balance`, `contracts_info`.`conclusion_date`, `contracts_info`.`activation_date`, `contracts_info`.`deactivation_date`,
`parents`.`mother_fullname`, `parents`.`mother_email`, `parents`.`mother_phone`, `parents`.`father_fullname`, `parents`.`father_email`, `parents`.`father_phone`, `parents`.`postal_office`,
`students`.`name`, `students`.`second_name`, `students`.`surname`, `students`.`form_number`, `students`.`form_letter`,
`students_info`.`medical_features`, `students_info`.`psychological_features`
FROM contracts_info
JOIN parents USING(contract_number)
JOIN students USING(contract_number)
JOIN students_info USING(contract_number)
WHERE MATCH (`contracts_info`.`contract_number`) AGAINST (? IN BOOLEAN MODE)
OR MATCH (`parents`.`contract_number`, `parents`.`mother_fullname`, `parents`.`mother_email`, `parents`.`father_fullname`, `parents`.`father_email`) AGAINST (? IN BOOLEAN MODE)
OR MATCH (`students`.`name`, `students`.`surname`, `students`.`contract_number`) AGAINST (? IN BOOLEAN MODE)
OR MATCH (`students_info`.`medical_features`, `students_info`.`psychological_features`, `students_info`.`contract_number`) AGAINST (? IN BOOLEAN MODE);
The problem is that when the query above is executed, I get an error from PDO class
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'contracts_info.contract_number' in 'where clause'
I've trying running a query with names enclosed in backquotes or not, this doesn't make any difference.
Queries without JOINS work well. Also I investigated these questions
mySQL MATCH across multiple tables
MySQL Optional LEFT JOIN With MATCH
but they didn't seem to have alike problem.
I don't understand why this happens because I give the exact name of columns and don't use AS aliases.
So why MySQL fails in finding and existing column from existing table?
MySQL version(): 5.6.29-76.2, PHP 5.5.9
Thank you in advance.
EDIT:
Table definitions:
CREATE TABLE IF NOT EXISTS `contracts_info` (
`contract_number` varchar(11) COLLATE utf8_unicode_ci NOT NULL,
`balance` decimal(7,2) unsigned zerofill NOT NULL,
`conclusion_date` date NOT NULL,
`activation_date` date NOT NULL,
`deactivation_date` date NOT NULL,
PRIMARY KEY (`contract_number`),
FULLTEXT KEY `contract_number` (`contract_number`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE IF NOT EXISTS `students` (
`contract_number` varchar(11) COLLATE utf8_unicode_ci NOT NULL,
`name` varchar(25) COLLATE utf8_unicode_ci NOT NULL,
`second_name` varchar(25) COLLATE utf8_unicode_ci NOT NULL,
`surname` varchar(25) COLLATE utf8_unicode_ci NOT NULL,
`form_number` enum('1','2','3','4','5','6','7','8','9','10','11','12') COLLATE utf8_unicode_ci NOT NULL,
`form_letter` enum('А','Б','В','Г','Д') COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`contract_number`),
FULLTEXT KEY `name` (`name`),
FULLTEXT KEY `surname` (`surname`),
FULLTEXT KEY `contract_number` (`contract_number`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE IF NOT EXISTS `students_info` (
`contract_number` varchar(11) COLLATE utf8_unicode_ci NOT NULL,
`medical_features` text COLLATE utf8_unicode_ci NOT NULL,
`psychological_features` text COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`contract_number`),
FULLTEXT KEY `medical_features` (`medical_features`),
FULLTEXT KEY `psycological_features` (`psychological_features`),
FULLTEXT KEY `contract_number` (`contract_number`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE IF NOT EXISTS `parents` (
`contract_number` varchar(11) COLLATE utf8_unicode_ci NOT NULL,
`mother_fullname` varchar(90) COLLATE utf8_unicode_ci NOT NULL,
`mother_email` varchar(45) COLLATE utf8_unicode_ci NOT NULL,
`mother_phone` decimal(15,0) NOT NULL,
`father_fullname` varchar(90) COLLATE utf8_unicode_ci NOT NULL,
`father_email` varchar(45) COLLATE utf8_unicode_ci NOT NULL,
`father_phone` decimal(15,0) NOT NULL,
`postal_office` int(4) NOT NULL,
PRIMARY KEY (`contract_number`),
FULLTEXT KEY `contract_number` (`contract_number`),
FULLTEXT KEY `mother_fullname` (`mother_fullname`),
FULLTEXT KEY `mother_email` (`mother_email`),
FULLTEXT KEY `father_fullname` (`father_fullname`),
FULLTEXT KEY `father_email` (`father_email`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

MYSQL query to find duplicate records based on first name and last name

I have a user table with following columns and i have come up with a query to identify the duplicate records based on the first name and last name.
table structure
CREATE TABLE IF NOT EXISTS `User` (
`id` bigint(20) NOT NULL,
`address1` text COLLATE utf8_unicode_ci,
`mobile` varchar(15) COLLATE utf8_unicode_ci DEFAULT NULL,
`name` varchar(45) COLLATE utf8_unicode_ci DEFAULT NULL,
`firstName` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
`lastName` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
`username` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL,
`password` varchar(45) COLLATE utf8_unicode_ci DEFAULT NULL,
`email` varchar(45) COLLATE utf8_unicode_ci DEFAULT NULL,
`gender` tinyint(2) NOT NULL DEFAULT '0' COMMENT '1 - female, 2-male, 0 - unknown',
`zip` varchar(15) COLLATE utf8_unicode_ci DEFAULT NULL,
`countryCode` varchar(3) COLLATE utf8_unicode_ci DEFAULT NULL,
`joinedDate` datetime DEFAULT NULL,
`dateOfBirth` date DEFAULT NULL COMMENT 'User date of birth'
) ENGINE=MyISAM AUTO_INCREMENT=63561 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
and my query
SELECT id, firstName, lastName, mobile, email, count(*) as dupCount
FROM `User` `t`
WHERE firstName is not null and lastName is not null
GROUP BY firstName,lastName HAVING count(*) > 1
ORDER BY t.joinedDate DESC
below is the screenshot of the result when i run the query
and my data set is here http://pastebin.com/Y5qsTcFc
sorry if paste bin is not working. try this https://drive.google.com/file/d/0B3gG6MG9uh7KdmRGT3d0NWg2aVk/view?usp=sharing
when there are records with email address is NULL, we have a problem. i am always getting this error.
1062 - Duplicate entry 'Rachel-Besnainou' for key 'group_key'
Query i ran is:
SELECT id, firstName, lastName, mobile, email, count(*) as dupCount
FROM `User` `t`
WHERE firstName is not null and lastName is not null
GROUP BY firstName,lastName
HAVING count(*) > 1
I have no idea why this error comes up. any help appreciated
Update 1
i try to add this to my database and ran the query still it was the same
SET SESSION max_heap_table_size=536870912;
SET SESSION tmp_table_size=536870912;
ref: Duplicate entry for key 'group_key'
Update 2
I tried the same database in diff mysql and phpmyadmin version and it worked. so looks like my mysql version has a bug. my mysql version is 5.6.26
Try this:
select a1.id,
a1.FirstName,
a1.LastName,
a1.mobile,
a1.email
from user a1
inner join
(
select FirstName, LastName, count(id)
from User
where firstname is not null
and lastname is not null
group by FirstName, LastName
having count(id)>1
) u1
on u1.FirstName = a1.Firstname
and u1.Lastname = a1.lastname
order by a1.joineddate

Find posts of user grouped by month, unixtime

I'd like to find the number of posts for each user grouped by month.
I'm currently using INT(10) unsigned to store the date of posts.
what would be a super fast way to do this?
CREATE TABLE IF NOT EXISTS `media` (
`pid` int(10) unsigned NOT NULL AUTO_INCREMENT,
`class` tinyint(1) NOT NULL DEFAULT '1',
`date_class_changed` int(10) unsigned NOT NULL,
`title` char(5) CHARACTER SET latin1 COLLATE latin1_general_cs NOT NULL,
`url` varchar(1024) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL,
`media` enum('image','video') CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL,
`thumb` varchar(255) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL,
`description` varchar(140) COLLATE utf8_unicode_ci NOT NULL,
`username` varchar(16) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL,
`date` int(10) unsigned NOT NULL,
`file` varchar(1024) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL,
`hash` char(32) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL,
`hashtag` text CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL,
`meta` varchar(255) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL,
`ip` int(10) unsigned NOT NULL,
`kind` tinyint(1) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`pid`),
UNIQUE KEY `title` (`title`),
KEY `hash` (`hash`),
KEY `class_date` (`class`,`date_class_changed`),
KEY `username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1022724 ;
This is the table, I'm talking about, I'd like to display the number of posts for each user for each mont, such as: september 2012, User X, N posts etc..
The query I'm using after the help from #fthiella is:
SELECT
DATE_FORMAT(FROM_UNIXTIME(`date`), '%Y-%m') as YearMonth, username, COUNT(*) as Posts
FROM
media
WHERE username = 'foobar'
GROUP BY 1
ORDER BY 1 DESC
thanks God it's fast enough, now I'll try to optimize in case it's not using an index, but for now with almost 1M record is doing good. cheers.
SELECT
DATE_FORMAT(FROM_UNIXTIME(`date`), '%Y-%m') as YearMonth,
username,
COUNT(*) as Posts
FROM
media
GROUP BY
DATE_FORMAT(FROM_UNIXTIME(`date`), '%Y-%m') as YearMonth,
username

Retrieve Data from Database and Count the number of times the data occurs

I have a couple of tables in MySQL that I'm working with that do not have any relation. They do have a column of similar data (Postal Codes / Zip Codes).
What I have to do with these tables is compare the postal codes from one table compare them to the postal codes from the first table and count them.
For Example.
Table A has a postal code of T0A and T0B (I use only the first three characters in the postal code as this is all I need to compare against)
Table B has 13 rows where the postal code matches T0A and 3 rows where the postal code matches T0B.
So the outcome would look like:
T0A = 13
T0B = 3
HOWEVER, then I need to take these and separate them by city, so since both T0A and T0B could be one city I would need to take those and add them together and get something like.
Edmonton = 16
I've been doing this with for loops and arrays. So I'm reading the data from table A into one array and the data from table b into another array. Then I compare the postal codes from table B to the postal codes in table A using nested for loops in order to count the number of occurrences of the postal codes and then I store them in another array. This is all fine and dandy however now I'm a bit stuck trying to separate the counts into their correct cities and I'm sitting here thinking there must be an easier way to do this. Does anyone have any suggestions, am I going about this all wrong?
Structure - Table A
jos_postalzip_redirect | CREATE TABLE `jos_postalzip_redirect` (
`id` int(11) NOT NULL auto_increment,
`country_code` varchar(2) NOT NULL,
`prov_state_code` varchar(2) NOT NULL,
`city` varchar(60) NOT NULL,
`postal_zip` varchar(6) NOT NULL,
`email_address` varchar(60) default NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=739 DEFAULT CHARSET=utf8 |
Structure - Table B
jos_form_submitteddata_form1 | CREATE TABLE `jos_form_submitteddata_form1` (
`id` int(11) NOT NULL auto_increment,
`bf_status` varchar(20) collate utf8_bin NOT NULL,
`bf_user_id` int(11) NOT NULL,
`FIELD_1` varchar(255) collate utf8_bin NOT NULL,
`FIELD_2` varchar(255) collate utf8_bin NOT NULL,
`FIELD_3` varchar(255) collate utf8_bin NOT NULL,
`FIELD_4` varchar(255) collate utf8_bin NOT NULL,
`FIELD_5` varchar(255) collate utf8_bin NOT NULL,
`FIELD_6` varchar(255) collate utf8_bin NOT NULL,
`FIELD_7` varchar(255) collate utf8_bin NOT NULL,
`FIELD_8` varchar(255) collate utf8_bin NOT NULL,
`FIELD_23` varchar(255) collate utf8_bin NOT NULL,
`FIELD_24` varchar(255) collate utf8_bin NOT NULL, //THIS IS THE POSTAL CODE FIELD
`FIELD_28` varchar(255) collate utf8_bin NOT NULL,
`FIELD_29` varchar(255) collate utf8_bin NOT NULL,
`FIELD_30` varchar(255) collate utf8_bin NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=4044 DEFAULT CHARSET=utf8 COLLATE=utf8_bin
Just an abstraction of what I understood. You may need to adjust it according to your needs.
In this example I will assume that FIELD_1 in table B is a postal code.
Count by postal code:
select
left(ta.postal_zip, 3) p_code, count(*)
from
jos_form_submitteddata_form1 tb
join jos_postalzip_redirect ta on left(tb.field_1, 3) = left(ta.postal_zip, 3)
group by
p_code
Count by city:
select
ta.city, count(*)
from
jos_form_submitteddata_form1 tb
join jos_postalzip_redirect ta on left(tb.field_1, 3) = left(ta.postal_zip, 3)
group by
ta.city

Selecting rows that corresponds from other table

I have a product table that stores all products. Also I have a production table that stores productions.
I am using CodeIgniter and datamapper ORM.
Here is tables:
CREATE TABLE IF NOT EXISTS `products` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`kod_stok` varchar(15) COLLATE utf8_unicode_ci DEFAULT NULL,
`kod_lokal` varchar(10) COLLATE utf8_unicode_ci DEFAULT NULL,
`kod_firma` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
`firma` varchar(15) COLLATE utf8_unicode_ci DEFAULT NULL,
`fabrika` varchar(10) COLLATE utf8_unicode_ci NOT NULL,
`proje` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
`tanim` mediumtext COLLATE utf8_unicode_ci,
`saatlik_uretim` int(11) NOT NULL,
`status` tinyint(4) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `kod_lokal` (`kod_lokal`),
KEY `kod_firma` (`kod_firma`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ;
CREATE TABLE IF NOT EXISTS `productions` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`fabrika` varchar(15) COLLATE utf8_unicode_ci DEFAULT NULL,
`board_no` int(11) NOT NULL,
`date` int(11) DEFAULT NULL, // Unix Timestamp
`operator_id` int(11) DEFAULT NULL,
`product_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `product` (`product_id`),
KEY `date` (`date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ;
I am trying to get count of production of given day. But not all products, producting everyday. I need to exlude the products that has 0 count.
$p = new Product();
$p->include_related_count('production');
$p->get();
And I want to add a date interval to production.
Basicly, I want to get all product's production count within a given day.
How can I do that?
Thank you for any advices.
Not sure about codeigniter details, but the following SQL query will generate a production list per day.
To get today's production:
$query = $this->db->query("
SELECT
a.count(*) as produced
, a.product_id
, b.kod_stok as productname
FROM productions a
INNER JOIN products b ON (a.product_id = b.id)
WHERE FROM_UNIXTIME(a.date) = CURDATE()
GROUP BY TO_DAYS(FROM_UNIXTIME(a.date)), a.product_id
");
To get last 7 days production
$query = $this->db->query("
SELECT
a.count(*) as produced
, a.product_id
, b.kod_stok as productname
FROM productions a
INNER JOIN products b ON (a.product_id = b.id)
WHERE FROM_UNIXTIME(a.date)
BETWEEN DATE_SUB(CURDATE(),INTERVAL 7 DAY) AND CURDATE()
GROUP BY TO_DAYS(FROM_UNIXTIME(a.date)), a.product_id
");

Categories