I need a joined (Union like) result from multiple databases on the same databaseserver in one query. Every customer database contains a location table and all customers are listed in the core database.
I don't need a simple join between to different databases. I need the actual joined database name to come from the same query.
I figure something like this.
SELECT customerlist.dbname,customerlist.realname,location.address
FROM core.customerlist
INNER JOIN `customer.dbname`.location
ORDER BY customerlist.realname
I know this won't work, I'm just trying to pseudo code what I'm searching for. I hope someone can help.
Database structure:
-- Database: `core`
CREATE TABLE IF NOT EXISTS `customerlist` (
`realname` varchar(20) NOT NULL,
`dbname` varchar(16) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `customerlist` (`realname`, `dbname`) VALUES
('Johnny', 'johnny'),
('Alfred', 'alfred');
-- --------------------------------------------------------
-- Database: `alfred`
CREATE TABLE IF NOT EXISTS `location` (
`address` varchar(20) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `location` (`address`) VALUES
('House Three'),
('Car 1');
-- --------------------------------------------------------
-- Database: `johnny`
CREATE TABLE IF NOT EXISTS `location` (
`address` varchar(20) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `location` (`address`) VALUES
('House One'),
('House Two');
Desired result;
johnny,Johnny,House One
johnny,Johnny,House Two
alfred,Alfred,House Three
alfred,Alfred,Car 1
You'll have to be careful of the two table identical tables...joining them in a union if fine since they are identical in structure:
SELECT customerlist.dbname,customerlist.realname,location.address
FROM core.customerlist
LEFT JOIN (
SELECT * FROM (johnny.location UNION alfred.location
)) AS T2 ON customerlist.dbname = T2.dbname
ORDER BY customerlist.realname
Related
I can generate federated tables from an opencart database to my local database without issue. However, one particular table (option_descriptions) returns no data to its federated (local) table despite there being data in the source table.
I thought this might be a problem with constraints or indexes but have been able to exclude those issues. I expect the problem must be table definition related, but I have no idea what the specifics of that might be.
The problem can be recreated locally using the following script.
Just change the #connection_string variable to suit your database
Thanks in advance.
`
--
-- Federated Tables Problem
-- Results expected to show 11 for both tables / databases
-- I don't understand why table_2 returns no data on the federated table
--
-- ------------------ ------ ----------
-- TABLE NAME SOURCE FEDERATED
-- ------------------ ------ ----------
-- TABLE_1 Row Count 11 11
-- TABLE_2 Row Count 11 << 0 >>
-- ------------------ ------ ----------
-- The following script generates the result above.
-- Modify this to suit ...
SET #connection_string = "mysql://root:trapdoor#localhost:3306";
-- Create a local database to contain a pair of tables as a source
--
DROP DATABASE IF EXISTS `fed_test_source`;
CREATE DATABASE `fed_test_source`;
USE fed_test_source;
CREATE TABLE `TABLE_1` (
`option_id` INT(11) NOT NULL AUTO_INCREMENT,
`type` VARCHAR(32) NOT NULL,
`sort_order` INT(3) NOT NULL,
PRIMARY KEY (`option_id`)
) ENGINE=MYISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
INSERT INTO `TABLE_1` (`option_id`, `type`, `sort_order`)
VALUES('1','select','15')
,('2','select','30')
,('3','radio','10')
,('4','select','20')
,('5','select','-100')
,('6','select','100')
,('7','select','0')
,('8','select','45')
,('9','select','0')
,('10','select','0')
,('11','select','0');
CREATE TABLE `TABLE_2` (
`option_id` INT(11) NOT NULL,
`language_id` INT(11) NOT NULL,
`name` VARCHAR(128) NOT NULL,
PRIMARY KEY (`option_id`,`language_id`)
) ENGINE=MYISAM DEFAULT CHARSET=utf8;
INSERT INTO `TABLE_2` (`option_id`, `language_id`, `name`)
VALUES('1','1','Barrel Length')
,('2','1','Cast')
,('3','1','Colour')
,('4','1','Size')
,('5','1','Calibre')
,('6','1','Pitch')
,('7','1','Power Level')
,('8','1','Weight')
,('9','1','Capacity')
,('10','1','Length')
,('11','1','Type');
-- Now create a pair of federated tables linked to the tables created above
DROP DATABASE IF EXISTS `fed_test`;
CREATE DATABASE `fed_test`;
USE fed_test;
DROP TABLE IF EXISTS `fed_TABLE_1`;
DROP TABLE IF EXISTS `fed_TABLE_2`;
-- Create federated table fed_TABLE_1;
SET #sqlstr = CONCAT("
CREATE TABLE `fed_TABLE_1` (
`option_id` BIGINT(20) NOT NULL AUTO_INCREMENT, -- change
`type` VARCHAR(32) NOT NULL,
`sort_order` INT(3) NOT NULL,
PRIMARY KEY (`option_id`)
) ENGINE=FEDERATED
AUTO_INCREMENT=1
DEFAULT CHARSET=utf8
CONNECTION='",
#connection_string,
"/fed_test_source/TABLE_1';");
PREPARE stmt FROM #sqlstr;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- Create federated table fed_TABLE_2;
SET #sqlstr = CONCAT("
CREATE TABLE `fed_TABLE_2` (
`option_id` BIGINT(20) NOT NULL,
`language_id` INT(11) NOT NULL,
`name` VARCHAR(128) NOT NULL,
PRIMARY KEY (`option_id`,`language_id`)
) ENGINE=MYISAM DEFAULT CHARSET=utf8
CONNECTION='",
#connection_string,
"/fed_test_source/TABLE_2';");
PREPARE stmt FROM #sqlstr;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SELECT 'TABLE_1 Row Count' `name`, (SELECT COUNT(*) `row count` FROM `fed_test_source`.`TABLE_1`) `SOURCE`,(SELECT COUNT(*) `row count` FROM fed_test.`fed_TABLE_1`) `FEDERATED`
UNION
SELECT 'TABLE_2 Row Count' `name`, (SELECT COUNT(*) `row count` FROM `fed_test_source`.`TABLE_2`) `SOURCE`,(SELECT COUNT(*) `row count` FROM fed_test.`fed_TABLE_2`) `FEDERATED`;
`
Based on the script provided, I would expect the row count for both tables, across remote and source databases, to be equivalent.
I am getting no data on the federated table for one of the sample tables generated in the script.
I have tried using different databases as SOURCE.
-- Sample data, borrowed from https://stackoverflow.com/q/7745609/808921
CREATE TABLE IF NOT EXISTS `docs` (
`id` int(6) NOT NULL auto_increment,
`groupname` varchar(100),
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `sm` (
`id` int(6) NOT NULL auto_increment,
`code` varchar(100),
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
INSERT INTO `docs` (`groupname`) VALUES
('100:2000'),
('100:2001'),
('101:2000'),
('101:2001'),
('102:2002'),
('103:2003');
INSERT INTO `sm` (`code`) VALUES
('100'),
('101'),
('2000');
SQL Fiddle of same: http://sqlfiddle.com/#!9/54714e/39
In MySQL, I would like to filter only the group names that contains various combinations of values in the sm table. i.e. 100,101,2000.
The below query returns other combinations too like
100:2000
100:2001
101:2000
101:2001
SQL:-
select distinct d.groupname from docs d, sm s where d.groupname like concat(s.code,'%') or d.groupname like concat('%',s.code);
Original question:-
mysql query to find all possible like combinations start with and ends with
Update:-
Expected results:-
100:2000
101:2000
I've just broke your or condition into make multiple join with the same table like below to achieve your expected result,
select distinct d.groupname from docs d
join sm s1 on
d.groupname like concat(s1.code,'%')
join sm s2 on
d.groupname like concat('%',s2.code);
I have this structure of my db:
CREATE TABLE IF NOT EXISTS `peoples` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;
For customers.
CREATE TABLE IF NOT EXISTS `peoplesaddresses` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`people_id` int(10) unsigned NOT NULL,
`phone` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
`address` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;
For their addresses.
CREATE TABLE IF NOT EXISTS `peoplesphones` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`people_id` int(10) unsigned NOT NULL,
`phone` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
`address` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;
For their phones.
UPD4
ALTER TABLE peoplesaddresses DISABLE KEYS;
ALTER TABLE peoplesphones DISABLE KEYS;
ALTER TABLE peoplesaddresses ADD INDEX i_phone (phone);
ALTER TABLE peoplesphones ADD INDEX i_phone (phone);
ALTER TABLE peoplesaddresses ADD INDEX i_address (address);
ALTER TABLE peoplesphones ADD INDEX i_address (address);
ALTER TABLE peoplesaddresses ENABLE KEYS;
ALTER TABLE peoplesphones ENABLE KEYS;
END UPD4
CREATE TABLE IF NOT EXISTS `order` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`people_id` int(10) unsigned NOT NULL,
`name` varchar(255) CHARACTER SET utf8 NOT NULL,
`phone` varchar(255) CHARACTER SET utf8 NOT NULL,
`adress` varchar(255) CHARACTER SET utf8 NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=12 ;
INSERT INTO `order` (`id`, `people_id`, `name`, `phone`, `adress`) VALUES
(1, 0, 'name1', 'phone1', 'address1'),
(2, 0, 'name1_1', 'phone1', 'address1_1'),
(3, 0, 'name1_1', 'phone1', 'address1_2'),
(4, 0, 'name2', 'phone2', 'address2'),
(5, 0, 'name2_1', 'phone2', 'address2_1'),
(6, 0, 'name3', 'phone3', 'address3'),
(7, 0, 'name4', 'phone4', 'address4'),
(8, 0, 'name1_1', 'phone5', 'address1_1'),
(9, 0, 'name1_1', 'phone5', 'address1_2'),
(11, 0, 'name1', 'phone1', 'address1'),
(10, 0, 'name1', 'phone1', 'address1');
Production base have over 9000 records. Is there way to execute this 3 update query's little more faster, than now (~50 min on dev machine).
INSERT INTO peoplesphones( phone, address )
SELECT DISTINCT `order`.phone, `order`.adress
FROM `order`
GROUP BY `order`.phone;
Fill peoplesphones table with unique phones
INSERT INTO peoplesaddresses( phone, address )
SELECT DISTINCT `order`.phone, `order`.adress
FROM `order`
GROUP BY `order`.adress;
Fill peoplesaddresses table with unique adress.
The next three querys are very slow:
UPDATE peoplesaddresses, peoplesphones SET peoplesaddresses.people_id = peoplesphones.id WHERE peoplesaddresses.phone = peoplesphones.phone;
UPDATE peoplesaddresses, peoplesphones SET peoplesphones.people_id = peoplesaddresses.people_id WHERE peoplesaddresses.address = peoplesphones.address;
UPDATE `order`, `peoplesphones` SET `order`.people_id = `peoplesphones`.people_id where `order`.phone = `peoplesphones`.phone;
Finally fill people table, and clear uneccessary fields.
INSERT INTO peoples( id, name )
SELECT DISTINCT `order`.people_id, `order`.name
FROM `order`
GROUP BY `order`.people_id;
ALTER TABLE `peoplesphones`
DROP `address`;
ALTER TABLE `peoplesaddresses`
DROP `phone`;
So, again: How can I make those UPDATE query's a little more faster? THX.
UPD: I forgott to say: I need to do it at once, just for migrate phones and adresses into other tables since one people can have more than one phone, and can order pizza not only at home.
UPD2:
UPD3:
Replace slow update querys on this (without with) get nothing.
UPDATE peoplesaddresses
LEFT JOIN
peoplesphones
ON peoplesaddresses.phone = peoplesphones.phone
SET peoplesaddresses.people_id = peoplesphones.id;
UPDATE peoplesphones
LEFT JOIN
`peoplesaddresses`
ON `peoplesaddresses`.address = `peoplesphones`.address
SET `peoplesphones`.people_id = `peoplesaddresses`.people_id;
UPDATE `order`
LEFT JOIN
`peoplesphones`
ON `order`.phone = `peoplesphones`.phone
SET `order`.people_id = `peoplesphones`.people_id;
UPD4 After adding code at the top (upd4), script takes a few seconds for execute. But on ~6.5k query it terminate with text: "The system cannot find the Drive specified".
Thanks to All. Especially to xQbert and Brent Baisley.
50 minutes for 9000 records is a bit ridiculous, event without indexes. You might as well put the 9000 records in Excel and do what you need to do. I think there is something else going on with your dev machine. Perhaps you have mysql configured to use very little memory? Maybe you can post the results of this "query":
show variables like "%size%";
Just this morning I did an insert(ignore)/select on 2 tables (one into another), both with over 400,000 records. 126,000 records were inserted into the second table, it took a total of 2 minutes 13 seconds.
I would say put indexes on any of the fields you are joining or grouping on, but this seems like a one time job. I don't think the lack of indexes is your problem.
All write operations are slow in relational databases. Especially indexes make them slow, since they have to be recalculated.
If you're using a WHERE in your statements, you should place an index on the fields referenced.
GROUP BY is always very slow, and so is DISTINCT, since they have to do a lot of checks that don't scale linearly. Always avoid them.
You may like to choose a different database engine for what you're doing. 9000 records in 50 minutes is very slow. Experiment with a few different engines, such as MyISAM and InnoDB. If you're using temporary tables a lot, MEMORY is really fast for those.
Update: Also, updating multiple tables in one statement probably shouldn't be done.
I want make query select all names from table 'a' where from table 'b' i have id_one='3'. id_two is id record from table
'a', two records have relation from id_one='3'. How i can make query ?
CREATE TABLE IF NOT EXISTS `a` (
`id` int(11) NOT NULL,
`name` varchar(11) NOT NULL,
`value` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--
-- Zrzut danych tabeli `a`
--
INSERT INTO `a` (`id`, `name`, `value`) VALUES
(1, 'lalala', 0),
(2, 'allalala', 0);
CREATE TABLE IF NOT EXISTS `b` (
`id_one` int(11) NOT NULL,
`id_two` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--
-- Zrzut danych tabeli `b`
--
INSERT INTO `b` (`id_one`, `id_two`) VALUES
(3, 1),
(3, 2);
This is what you want:
select Name
from a inner join b on a.id = b.id_two
where b.id_one = 3
sorry I'm not fully understanding your schemas or your question, but I think what you're trying to ask for is:
SELECT * FROM a
JOIN b on a.id = b.id_two;
Try that.
Your question title mentions left joins, but you don't need a left join to make the query you described.
Left joins are good for finding things that don't match up the way you'd expect. So, using a left join in this case depends on what you are looking for. If you are looking for b.id_two entries that don't have corresponding table a entries,
select Name, b.* from b left join a on a.id = b.id_two
This will give you a table that lists every row in table b, with NULLs in place of the names for table a where there is no match.
Likewise, if you are looking for names that don't have entries in b.id_two, you would use
select Name, b.* from a left join b on a.id = b.id_two
If you want to enforce that there is always a correspondence, you can define a foreign key constraint between the parent and child table.
select Name
from a join b on a.id = b.id_two
where b.id_one = 3;
Will also work to get your answer. Might I also suggest you significantly improve your create table statements to include indexing. E.G.
CREATE TABLE IF NOT EXISTS `a` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(11) NOT NULL,
`value` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS `b` (
`id_one` bigint(20) NOT NULL,
`id_two` bigint(20) NOT NULL,
KEY `FKCAFBB09382DEAC` (`id_one`),
CONSTRAINT `b_a_1` FOREIGN KEY (`id_two`) REFERENCES `a` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
I would also use bigint for primary keys and use charset=utf8
these days it is just to common to want to migrate application to multi-lingual, lay the ground work now. IMHO
I have two tables:
product_description( name , product_id)
product( quantity, stock_status_id, price, product_id)
What I am trying to do is run a query that will get me the above data but I am not sure how to implement a join to get the joined data from both tables.
Resolved
I did the following:
SELECT product_description.name, product.quantity,product.price
FROM product
INNER JOIN product_description
ON product.product_id=product_description.product_id
ORDER BY product_description.name
Operating under the assumption that you have matching product_ids in each table, here's a query that will return the data you need using implicit joins:
SELECT product.product_id, name, quantity, stock_status_id, price
FROM product, product_description
WHERE product.product_id = product_description.product_id
UPDATE:
This works as I would expect. Here are two table dumps that might help you, and the output of the query.
product table:
--
-- Table structure for table `product`
--
CREATE TABLE IF NOT EXISTS `product` (
`product_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(256) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`product_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=3 ;
--
-- Dumping data for table `product`
--
INSERT INTO `product` (`product_id`, `name`) VALUES
(1, 'Croissant'),
(2, 'Danish');
product_description table:
--
-- Table structure for table `product_description`
--
CREATE TABLE IF NOT EXISTS `product_description` (
`product_id` int(11) NOT NULL,
`quantity` int(11) NOT NULL,
`stock_status_id` int(11) NOT NULL,
`price` double NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
--
-- Dumping data for table `product_description`
--
INSERT INTO `product_description` (`product_id`, `quantity`, `stock_status_id`, `price`) VALUES
(1, 6, 2, 12.5),
(2, 13, 1, 19.25);
Output from the above query:
"1","Croissant","6","2","12.5"
"2","Danish","13","1","19.25"
maybe something like this?
select p.id, p.quantity, p.stock_status_id, p.price, d.name
from Product p inner join `Product Description` d on d.product_id=p.id
although I'm still not sure of what the table schema actually looks like from the description in the question.
SELECT
-- name each column you want here
-- prefix columns from the PRODUCT table with its alias like so:
p.product_id,
-- prefix columns from the other table as its alias
d.quantity
FROM
PRODUCT p -- name of your PRODUCT table aliased as p
INNER JOIN -- join against your other table
PRODUCT_DESCRIPTION d -- name of your other table aliased as d
ON
p.product_id = d.product_id -- match the foreign keys
See INNER JOIN documentation for more details.
NOTE: This won't work as-is, you'll need to provide the columns that you want from each table in the SELECT clause, and probably fix the table names to match for your application.