I'm trying to do a full-text search in two separate tables and sort the results by relevancy. I am not getting a relevant data. below is my tables structure and my query which I am using
- I have two tables "deals" and "outlets" now I want to do full text search as user can search with title only and with the address as well. Please see the tables and query
Table1:
CREATE TABLE `deals` (
`id` int(11) NOT NULL,
`outlet_store_id` int(6) DEFAULT NULL,
`title` varchar(250) DEFAULT NULL,
`description` text,
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `deals` (`id`, `outlet_store_id`, `title`, `description`, `created_at`, `updated_at`) VALUES
(1, 1, 'Great Deal Flat 50% Off', '40% of on all the shoes', '2017-09-10 00:00:00', '2017-09-05 05:08:14'),
(5, 4, 'Flat 50% off', 'sdfsdf sfsdf ds', '2017-09-12 11:54:14', '2017-09-12 11:57:03');
--
-- Indexes for dumped tables
--
--
-- Indexes for table `deals`
--
ALTER TABLE `deals`
ADD PRIMARY KEY (`id`);
ALTER TABLE `deals` ADD FULLTEXT KEY `title` (`title`);
**Table 2**
CREATE TABLE `outlet_stores` (
`id` int(11) NOT NULL,
`name` varchar(200) DEFAULT NULL,
`address` text,
`longitude` varchar(30) DEFAULT NULL,
`latitude` varchar(30) DEFAULT NULL,
`status` tinyint(2) NOT NULL DEFAULT '1',
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--
-- Dumping data for table `outlet_stores`
--
INSERT INTO `outlet_stores` (`id`, `name`, `address`, `longitude`, `latitude`, `status`, `created_at`, `updated_at`) VALUES
(1, 'Polo-011', 'SCO-89,90,91, 1st Floor, Sector 17 D', '76.755181', '30.734015', 0, '2017-08-22 00:00:00', '2017-09-06 11:47:49'),
(3, 'Tommy Highflier', 'SCO 11-12, Sector 17D, Chandigarh', NULL, NULL, 1, '2017-09-05 11:09:48', '2017-09-05 11:09:48'),
(4, 'Kapson Store', 'Elante Mall, Chandigarh', NULL, NULL, 1, '2017-09-12 11:20:50', '2017-09-12 11:20:50');
--
-- Indexes for dumped tables
--
--
-- Indexes for table `outlet_stores`
--
ALTER TABLE `outlet_stores`
ADD PRIMARY KEY (`id`);
ALTER TABLE `outlet_stores` ADD FULLTEXT KEY `address` (`address`);
What I want
There is only one input on my website and User can search with "Flat 50% off" and "Flat 50% off in elante mall" so after my query I am getting same records I want if user search with "flat" then it returns all the records and if user search with location then it return actual match and if there is no records then it returns empty but some suggestions suppose "Flat 50% off in elante mall" if there is no record then it search with flat 50% and returns some suggestion results.
My query which I am using
SELECT *,
MATCH(deals.title) AGAINST($q) as deals,
MATCH(outlet_stores.address) AGAINST($q) as outlet_stores
FROM deals
LEFT JOIN outlet_stores ON deals.outlet_store_id = outlet_stores.id
WHERE
MATCH(deals.title) AGAINST($q)
OR MATCH(outlet_stores.address) AGAINST($q);
Related
While importing the sql data, it shows syntax error:
Here is my code:
CREATE TABLE IF NOT EXISTS `tblproduct` (
`id` int(8) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`code` varchar(255) NOT NULL,
`image` text NOT NULL,
`price` double(10,2) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `product_code` (`code`)
)
INSERT INTO `tblproduct` (`id`, `name`, `code`, `image`, `price`) VALUES
(1, '3D Camera', '3DcAM01', 'product-images/camera.jpg', 1500.00),
(2, 'External Hard Drive', 'USB02', 'product-images/external-hard-drive.jpg', 800.00),
(3, 'Wrist Watch', 'wristWear03', 'product-images/watch.jpg', 300.00);
I just confused with this, what is the exact error.
Can anyone help me to fix this? thanks in advance.
Looks like it's whole generated so there should be no errors. Try to add semicolon after create table syntax so each query is separated. Like this:
CREATE TABLE IF NOT EXISTS `tblproduct` (
`id` int(8) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`code` varchar(255) NOT NULL,
`image` text NOT NULL,
`price` double(10,2) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `product_code` (`code`)
);
INSERT INTO `tblproduct` (`id`, `name`, `code`, `image`, `price`) VALUES
(1, '3D Camera', '3DcAM01', 'product-images/camera.jpg', 1500.00),
(2, 'External Hard Drive', 'USB02', 'product-images/external-hard-drive.jpg', 800.00),
(3, 'Wrist Watch', 'wristWear03', 'product-images/watch.jpg', 300.00);
I have 2 tables 'cat' and 'sub_cat' and these two tables should join or something with main table 'product'
I tried all joining methods and non of them gave me right result I want.
I'm sure there is a method. I don't know what to call.
Sample SQL
This is how the last query should be
forget about the normalization theories and every thing and I just want the last query to be like this or mysql method that I can use on this.
cat_id cannot be duplicate
s_id should also cannot be duplicate
like in third row there can be: cat_id but no s_id the s_id should be null
if there is no cat_id and no s_id both should be null like fourth row
p_id can be duplicate
can't use group by or distinct cause it doesn't give null values then as i know
only method i got closer is using left joining both cat and sub_cat to prod table but it gives me duplicate cat_id and s_id and can't use group by or distinct on this cause there should be null values.
here is the test data
CREATE TABLE IF NOT EXISTS `cat` (
`product_id` int(11) DEFAULT NULL,
`cat_id` int(11) DEFAULT NULL,
`cat_name` varchar(10) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `cat` (`product_id`, `cat_id`, `cat_name`) VALUES
(1, 1, 'cat1'),
(2, 2, 'cat2'),
(3, 3, 'cat3'),
(1, 4, 'ca4');
CREATE TABLE IF NOT EXISTS `prod` (
`product_id` int(11) DEFAULT NULL,
`name` varchar(10) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `prod` (`product_id`, `name`) VALUES
(1, 'prod1'),
(2, 'prod2'),
(3, 'pro3'),
(4, 'prod4');
CREATE TABLE IF NOT EXISTS `sub_cat` (
`product_id` int(11) DEFAULT NULL,
`sub_cat_id` int(11) DEFAULT NULL,
`sub_cat_name` varchar(10) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `sub_cat` (`product_id`, `sub_cat_id`, `sub_cat_name`) VALUES
(1, 1, 'sub cat 1'),
(2, 2, 'sub cat 2'),
(1, 3, 'sub3');
I have done a similar thing in this one.prop_cat acts as you Category table,prop_subcat as your subcategory table and property as you product.
CREATE TABLE `prop_cat` (
`pcat_id` int(11) NOT NULL AUTO_INCREMENT,
`pcat_name` varchar(60) DEFAULT NULL,
PRIMARY KEY (`pcat_id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
CREATE TABLE `prop_subcat` (
`psubcat_id` int(11) NOT NULL,
`pcat_id` int(11) NOT NULL,
`psubcat_name` varchar(45) DEFAULT NULL,
PRIMARY KEY (`psubcat_id`,`pcat_id`),
KEY `pspc_idx` (`pcat_id`),
CONSTRAINT `catsub` FOREIGN KEY (`pcat_id`) REFERENCES `prop_cat` (`pcat_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `property` (
`prop_id` int(11) NOT NULL AUTO_INCREMENT,
`prop_name` varchar(25) DEFAULT NULL,
`price` double DEFAULT NULL,
`location` varchar(50) DEFAULT NULL,
`image` varchar(60) DEFAULT NULL,
`area` double DEFAULT NULL,
`psubcat_id` int(11) DEFAULT NULL,
`description` text,
PRIMARY KEY (`prop_id`),
KEY `psub_idx` (`psubcat_id`),
CONSTRAINT `psub` FOREIGN KEY (`psubcat_id`) REFERENCES `prop_subcat` (`pcat_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
SELECT
prop_cat.`pcat_id` AS prop_cat_pcat_id,
prop_cat.`pcat_name` AS prop_cat_pcat_name,
prop_subcat.`psubcat_id` AS prop_subcat_psubcat_id,
prop_subcat.`pcat_id` AS prop_subcat_pcat_id,
prop_subcat.`psubcat_name` AS prop_subcat_psubcat_name,
property.`prop_id` AS property_prop_id,
property.`prop_name` AS property_prop_name,
property.`price` AS property_price,
property.`location` AS property_location,
property.`image` AS property_image,
property.`area` AS property_area,
property.`psubcat_id` AS property_psubcat_id,
property.`description` AS property_description
FROM
`prop_cat` prop_cat INNER JOIN `prop_subcat` prop_subcat ON prop_cat.`pcat_id` = prop_subcat.`pcat_id`
INNER JOIN `property` property ON prop_subcat.`pcat_id` = property.`psubcat_id`
I'm not sure how to get the result that I expect and I've tried everything. I also need to be able to get the expected results using one query.
Here are the two tables with some sample data:
--
-- Table structure for table `accounts`
--
CREATE TABLE IF NOT EXISTS `accounts` (
`id` int(11) NOT NULL,
`name` varchar(200) NOT NULL,
`type_id` int(11) NOT NULL,
`description` varchar(200) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
--
-- Data for table `accounts`
--
INSERT INTO `accounts` (`id`, `name`, `type_id`, `description`) VALUES
(100, 'DUES', 0, NULL),
(101, 'NET WEEKLY PAYROLL', 0, NULL),
(111, 'FEDERAL TAX DEPOSITS', 0, 'tax stuff'),
(113, 'UNITED ASSOCIATION PAYMENTS', 0, NULL),
(114, 'OFFICERS MEETING ALLOWANCES', 0, NULL);
--
-- Table structure for table `checks`
--
CREATE TABLE IF NOT EXISTS `checks` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`batch_id` int(11) DEFAULT NULL,
`entry_date` date NOT NULL,
`account_id` int(11) NOT NULL,
`amount` decimal(10,2) NOT NULL,
`description` varchar(200) DEFAULT NULL,
`posted` tinyint(4) NOT NULL DEFAULT '0',
`vendor_id` int(11) DEFAULT NULL,
`check_num` int(11) NOT NULL,
`voided` tinyint(4) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;
--
-- Dumping data for table `checks`
--
INSERT INTO `checks` (`id`, `batch_id`, `entry_date`, `account_id`, `amount`, `description`, `posted`, `vendor_id`, `check_num`, `voided`) VALUES
(1, NULL, '2013-01-21', 111, '77.44', 'Last Year', 0, 1, 100, 0),
(2, NULL, '2014-01-21', 111, '521.11', 'Test Stuff', 0, 1, 101, 0),
(3, NULL, '2014-01-20', 101, '121.11', 'More Tests', 0, 1, 222, 0),
(4, NULL, '2014-01-02', 101, '150.00', 'test', 0, 4, 213, 0);
I want to create a list of all accounts with a month-to-date sum as an added field. Here is the query to get the month-to-date sum without joining the accounts table:
SELECT *, SUM(amount) as mtd FROM `checks` WHERE `entry_date` > '2014-01-01' GROUP BY `account_id`
... and here is what i used to get all the accounts joined to checks table:
SELECT * FROM `accounts` LEFT OUTER JOIN `checks` ON `checks.account_id` = `accounts.id`
I just can't seem to combine these two correctly to get the expected results. Please help!
I think this solves your problem:
SELECT a.*, SUM(c.amount) as mtd
FROM accounts a left outer join
checks c
ON (a.id = c.account_id) and c.entry_date >= '2014-01-01'
GROUP BY a.account_id;
This will return all accounts, even those with no activity in January. I changed the date condition to >=, because that "feels" better as a month-to-date cutoff.
I am using the following sql statement to sum values from two columns from two different tables. The statement can output but not the desired result.
SELECT
SUM(`_income`.rate) AS Income,
SUM(`_expense`.rate) AS Expense,
SUM(_income.rate)-SUM(_expense.rate) AS Balance
FROM `_expense`, `_income`
My table is here:
CREATE TABLE IF NOT EXISTS `_expense` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`item` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`qnty` int(11) NOT NULL,
`rate` int(11) NOT NULL,
`date` date NOT NULL,
`CreatedByPHPRunner` int(11) NOT NULL,
`remarks` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;
--
-- Dumping data for table _expense
INSERT INTO `_expense` (`id`, `item`, `qnty`, `rate`, `date`, `CreatedByPHPRunner`, `remarks`) VALUES
(2, 'Maian', 2, 20, '2013-08-15', 0, 'A tui kher mai'),
(3, 'Battery', 1, 2100, '2013-08-15', 0, 'A lian chi');
--
-- Table structure for table _income
CREATE TABLE IF NOT EXISTS `_income` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`items` varchar(100) DEFAULT NULL,
`qnty` int(11) DEFAULT NULL,
`rate` int(11) DEFAULT NULL,
`date` date DEFAULT NULL,
`remarks` varchar(255) DEFAULT NULL,
`CreatedByPHPRunner` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;
--
-- Dumping data for table _income
INSERT INTO `_income` (`id`, `items`, `qnty`, `rate`, `date`, `remarks`, `CreatedByPHPRunner`) VALUES
(1, 'TV chhe siam', 1, 1500, '2013-08-15', 'Ka hniam hrep', NULL),
(2, 'First Star', 1, 25, '2013-08-15', 'A loose-in aw', NULL),
(3, 'Mobile Chhe siam', 2, 200, '2013-08-13', 'Nokia chhuak ho a nia', NULL),
(4, 'Internet hman man', 1, 1500, '2013-08-14', 'Ka net min hman sak a', NULL);
This should do it:
select income, expense, income-expense balance
from (select sum(rate) income
from _income) i
JOIN (select sum(rate) expense
from _expense) e
I am using the following tables in my MySQL-Database:
--
-- Table structure for table `company`
--
CREATE TABLE IF NOT EXISTS `company` (
`numb` varchar(4) NOT NULL,
`cik` varchar(30) NOT NULL,
`sNumber` varchar(30) NOT NULL,
`street1` varchar(255) NOT NULL,
`street2` varchar(255) NOT NULL,
`city` varchar(255) NOT NULL,
`state` varchar(100) NOT NULL,
`zip` varchar(100) NOT NULL,
`phone` varchar(255) NOT NULL,
`name` varchar(255) NOT NULL,
`dateChanged` varchar(30) NOT NULL,
`name2` varchar(255) NOT NULL,
`seriesId` varchar(30) NOT NULL,
`symbol` varchar(10) NOT NULL,
`exchange` varchar(20) NOT NULL,
PRIMARY KEY (`cik`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `company` (`numb`, `cik`, `sNumber`, `street1`, `street2`, `city`, `state`, `zip`, `phone`, `name`, `dateChanged`, `name2`, `seriesId`, `symbol`, `exchange`) VALUES
('6798', 'abc', '953551121', '701 AVENUE', '', 'GLENDALE', 'CA', '91201-2349', '818-244-8080', '', '', 'Public Store', '', 'PSA', 'NYSE')
--
-- Table structure for table `data`
--
CREATE TABLE IF NOT EXISTS `data` (
`id` int(100) NOT NULL AUTO_INCREMENT,
`number` varchar(100) NOT NULL,
`elementname` mediumtext NOT NULL,
`date` varchar(100) NOT NULL,
`elementvalue` longtext NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=18439;
INSERT INTO `data` (`id`, `number`, `elementname`, `date`, `elementvalue`) VALUES
(1, '0001393311-10-000004', 'StockholdersEquityIncludingPortionAttributableToNoncontrollingInterest', '2009-12-31', '3399777000')
--
-- Table structure for table `filing`
--
CREATE TABLE IF NOT EXISTS `filing` (
`number` varchar(100) NOT NULL,
`file_number` varchar(100) NOT NULL,
`type` varchar(100) NOT NULL,
`amendment` tinyint(1) NOT NULL,
`date` varchar(100) NOT NULL,
`cik` varchar(30) NOT NULL,
PRIMARY KEY (`accession_number`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `filing` (`number`, `file_number`, `type`, `amendment`, `date`, `cik`) VALUES
('0001393311-10-000004', '001-33519', '10-K', 0, '2009-12-31', '0000751653'),
('0000751652-10-000006', '001-08796', '10-K', 0, '2009-12-31', '0000751652')
The data table has around 22.000 entries, filing and company tables have around 400 entries each. I want to operate the database with a lot more entries in the future.
I perform the following query, which selects the newest item with a given type:
SELECT data.elementname, data.elementvalue, company.name2 FROM data
JOIN filing ON data.number = filing.number
JOIN company ON filing.cik = company.cik
WHERE elementname IN ('Elem1', 'Elem2', 'Elem3', 'Elem4', 'Elem5', 'ElemN')
AND number IN (
SELECT number
FROM filing
WHERE filing.cik IN ('cik1', 'cik2', 'cikN')
AND filing.type = '1L'
GROUP BY filing.cik
)
It takes between ~0.28 and 0.4 seconds to complete, which appears to be very slow.
When i perform the query without the following line
WHERE filing.cik IN ('cik1', 'cik2', 'cikN')
it takes only ~0.035 seconds.
Any idea how to speed the query up or to optimize the table structure because the table is growing rapidly and it's already too slow.
First off, the table structure you posted for filing is incorrect, as the primary key you specified doesn't. I'll assume you mean number. Additionally, you didn't specify the table definition for company, which makes trying to provide advice for this somewhat difficult.
However, both of the comments are correct. You need some indexes. Based on the query, you should probably some the following indexes.
ALTER TABLE company ADD INDEX ( cik )
ALTER TABLE data ADD INDEX ( number )
I would also recommend taking a look at whether data.elementname actually needs to be a MEDIUMTEXT, which is a pretty huge column. If the rest of the data looks like the example data you provided, you should probably change it into a varchar. TEXT columns can cause some serious performance penalties due to the way they're stored.
Additionally, your PRIMARY KEY number columns, which are currently strings, look as though they could be reformatted into different columns that are actually of type INT. Keep in mind that VARCHAR PRIMARY KEY columns will not be as efficient as INTs, just because they're so much bigger.
Lastly, 22k rows isn't all that much data. You should a take a look at your my.cnf settings. Your key_buffer value may be too small to fit indexes entirely in memory. Additionally, you may want to consider using INNODB for these tables, combined with an innodb_buffer_pool value that'll keep everything in memory.