I need to somehow order the ORDER BY column by using another table's order.
Table that contains sort:
CREATE TABLE IF NOT EXISTS `menu_category` (
`CATEGORY_ID` int(11) NOT NULL AUTO_INCREMENT,
`CATEGORY_NAME` varchar(20) NOT NULL,
`BUTTON_SORT` int(11) DEFAULT NULL,
PRIMARY KEY (`CATEGORY_ID`),
UNIQUE KEY `CATEGORY_NAME` (`CATEGORY_NAME`),
);
Keep in mind that BUTTON_SORT can be null.
Table that needs grouping:
CREATE TABLE IF NOT EXISTS `ticket_item` (
`TICKET_ITEM_ID` int(11) NOT NULL AUTO_INCREMENT,
`TICKET_ITEM_DESC` varchar(30) NOT NULL,
`TICKET_PRINT_CAT` varchar(40) NOT NULL,
PRIMARY KEY (`TICKET_ITEM_ID`),
);
I currently use this query:
SELECT
TICKET_ITEM_ID,
TICKET_ITEM_DESC
FROM ticket_item
WHERE
ticket_item.TICKET_ID = 1
GROUP BY TICKET_PRINT_CAT
What this ends up doing is that it will group everything correctly, but the order of which it is printed is just alphabetical. I need to sort the groups by order of BUTTON_SORT instead. I have no idea where to start for this.
EDIT: I apologize, TICKET_PRINT_CAT and CATEGORY_NAME are relative.
SELECT
TICKET_ITEM_ID,
TICKET_ITEM_DESC
FROM ticket_item
INNER JOIN menu_category ON menu_category.CATEGORY_NAME=ticket_item.TICKET_PRINT_CAT
WHERE
ticket_item.TICKET_ID = 1
GROUP BY TICKET_PRINT_CAT
ORDER BY menu_category.BUTTON_SORT
You need to use joins here. This creates a result set that can have values from both tables, and also can be ordered or grouped by values from either table.
SELECT
ticket_item.TICKET_ITEM_ID, ticket_item.TICKET_ITEM_DESC
FROM ticket_item
LEFT JOIN table2 on ticket_item.someColumnOnTable1 = table2.someColumnOnTable2
ORDER BY table2.whateverColumnYouWantToOrderBy
Related
To allow our customers to store some of their own data along with our data structure I have created two extra tables:
CREATE TABLE external_columns
(
`id` INT(11) PRIMARY KEY NOT NULL,
`column` VARCHAR(30) NOT NULL,
`sid` INT(11) NOT NULL,
`bid` INT(11) NOT NULL,
`label` VARCHAR(30) NOT NULL,
`table` VARCHAR(30) NOT NULL,
`default` TINYTEXT NOT NULL
);
CREATE TABLE external_data
(
`id` INT(11) PRIMARY KEY NOT NULL,
`extcol_id` INT(11) NOT NULL,
`sid` INT(11) NOT NULL,
`bid` INT(11) NOT NULL,
`data` MEDIUMTEXT NOT NULL,
`row_id` INT(11) NOT NULL,
CONSTRAINT `external_data_external_columns_id_fk`
FOREIGN KEY (extcol_id) REFERENCES external_columns (id)
);
CREATE UNIQUE INDEX combinedUniqueIndex
ON external_data (extcol_id, sid, bid, row_id);
sid and bid are system values that identify the customer the data belongs to. row_id refers to the primary key of table referenced in table.
To get data for a certain row I have created this prepared statement:
SELECT `data`.*, `columns`.`column`, `columns`.`default`
FROM `external_columns` as `columns`
LEFT JOIN `external_data` as `data`
ON `columns`.`id` = `data`.`extcol_id`
WHERE (
`columns`.`sid` = :sid
AND `columns`.`bid` = :bid
AND `data`.`row_id` = :row_id
AND `columns`.`table` = :tableName
)
This works fine as long as for each external_column there is an entry in external_data for the given :row_id. But I want to make sure that there is always a row for each column, even if there is no data for the given :row_id. Is there a way to do this with one query?
Very close, by placing AND data.row_id = :row_id in your WHERE, you have effectively written an INNER JOIN as nulled data.row_ids won't match.
You should move this condition to the LEFT JOIN conditions:
SELECT `data`.*, `columns`.`column`, `columns`.`default`
FROM `external_columns` as `columns`
LEFT JOIN `external_data` as `data`
ON `data`.`extcol_id`= `columns`.id
AND `data`.`row_id` = :row_id
WHERE `columns`.`sid` = :sid
AND `columns`.`bid` = :bid
AND `columns`.`table` = :tableName
Personal Preferences:
Don't need the WHERE parentheses and I always tend to put the table conditions for a JOIN in the JOIN conditions where applicable and JOIN table on the LHS to make indexing options more obvious..
No difference for INNER JOINs but essential for certain LEFT JOINs.
I need help writing a mysql query. I have two tables, one parent, one child.
Parent table: garments
`garment_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`description` text,
PRIMARY KEY (`garment_id`)
Child table: garment_images
`id` int(11) NOT NULL AUTO_INCREMENT,
`garment_id` int(11) NOT NULL,
`filename` varchar(100) NOT NULL,
`order` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
I would like query all garments, and to show the first image for each item from the 'garment_images' table.
This should be fairly close:
SELECT G.*, (
SELECT GI.id, GI.filename from garment_images as GI
WHERE GI.garment_id = G.garment_id
ORDER BY GI.order DESC
LIMIT 1)
FROM garments as G
Split the problem:
Retreive the first image id for every garment
Put the data together
Step 1:
select gi.*
from
garment_images as gi
inner join (
select min(id) as minId
from garment_images
group by garment_id
) as a on gi.garment_id = a.minId
I'll leave to you the second step (Hint: join the data from the query above with your garment table)
If "the first image" is the one with order = 1 (SQL Fiddle)
SELECT * from garments g JOIN garment_images gi
ON g.garment_id = gi.garment_id
WHERE gi.order = 1
I created these two tables:
CREATE TABLE `Game` (
`GameName` varchar(30) NOT NULL,
`GameGenre` varchar(20) NOT NULL,
`GameDescription` varchar(500) NOT NULL,
`GameMode` varchar(20) NOT NULL,
PRIMARY KEY (`GameName`)
) ENGINE=InnoDB;
CREATE TABLE `GameScoreTotal` (
`ScoreID` int(3) NOT NULL AUTO_INCREMENT,
`GameName` varchar(30) NOT NULL,
`OverallScoreTotal` mediumint(9) NOT NULL,
`GraphicsTotal` mediumint(9) NOT NULL,
`StoryTotal` mediumint(9) NOT NULL,
`GameplayTotal` mediumint(9) NOT NULL,
`TimeTotal` mediumint(9) NOT NULL,
PRIMARY KEY (`ScoreID`),
CONSTRAINT FOREIGN KEY (`GameName`) REFERENCES `Game` (`GameName`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB;
My query needs to return all information from game table for the top ten games based on GameScoreTotal.OverallScoreTotal.
Queries I have tried:
SELECT GameName
FROM Game
FULL JOIN GameScoreTotal
ON Game.GameName=GameScoreTotal.GameName
ORDER BY OverallScoreTotal DESC
LIMIT 0, 10;
SELECT Game.GameName
FROM Game
FULL JOIN GameScoreTotal
ON Game.GameName=GameScoreTotal.GameName
ORDER BY OverallScoreTotal DESC
LIMIT 0, 10;
Both tables have legitimate records within them.
Query 1
In your first query, the issue is that the field GameName exist in both the tables Game and GameScoreTotal. Hence the error Column 'GameName' in field list is ambiguous
Query 2
MySQL doesn't have a FULL JOIN. Read here about MySQL JOIN Syntax.
Try the LEFT OUTER JOIN between Game and GameScoreTotal table, this join will fetch all records from Game table and all the matching records from GameScoreTotal table, if there are no matching records in GameScoreTotal table, NULL will be displayed.
You can also try INNER JOIN, which will fetch only the matching records between the two tables.
Script:
SELECT Game.GameName
FROM Game
LEFT OUTER JOIN GameScoreTotal
ON Game.GameName=GameScoreTotal.GameName
ORDER BY OverallScoreTotal DESC
LIMIT 0, 10;
I need some help with a MySQL query. I have two tables, one with offers and one with statuses. An offer can has one or more statuses. What I would like to do is get all the offers and their latest status. For each status there's a table field named 'added' which can be used for sorting.
I know this can be easily done with two queries, but I need to make it with only one because I also have to apply some filters later in the project.
Here's my setup:
CREATE TABLE `test`.`offers` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`client` TEXT NOT NULL ,
`products` TEXT NOT NULL ,
`contact` TEXT NOT NULL
) ENGINE = MYISAM ;
CREATE TABLE `statuses` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`offer_id` int(11) NOT NULL,
`options` text NOT NULL,
`deadline` date NOT NULL,
`added` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
Should work but not very optimal imho :
SELECT *
FROM offers
INNER JOIN statuses ON (statuses.offer_id = offers.id
AND statuses.id =
(SELECT allStatuses.id
FROM statuses allStatuses
WHERE allStatuses.offer_id = offers.id
ORDER BY allStatuses.added DESC LIMIT 1))
Try this:
SELECT
o.*
FROM offers o
INNER JOIN statuses s ON o.id = s.offer_id
ORDER BY s.added
LIMIT 1
Looking at this query there's got to be something bogging it down that I'm not noticing. I ran it for 7 minutes and it only updated 2 rows.
//set product count for makes
$tru->query->run(array(
'name' => 'get-make-list',
'sql' => 'SELECT id, name FROM vehicle_make',
'connection' => 'core'
));
while($tempMake = $tru->query->getArray('get-make-list')) {
$tru->query->run(array(
'name' => 'update-product-count',
'sql' => 'UPDATE vehicle_make SET product_count = (
SELECT COUNT(product_id) FROM taxonomy_master WHERE v_id IN (
SELECT id FROM vehicle_catalog WHERE make_id = '.$tempMake['id'].'
)
) WHERE id = '.$tempMake['id'],
'connection' => 'core'
));
}
I'm sure this query can be optimized to perform better, but I can't think of how to do it.
vehicle_make = 45 rows
taxonomy_master = 11,223 rows
vehicle_catalog = 5,108 rows
All tables have appropriate indexes
UPDATE: I should note that this is a 1-time script so overhead isn't a big deal as long as it runs.
CREATE TABLE IF NOT EXISTS `vehicle_make` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(32) NOT NULL,
`product_count` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=46 ;
CREATE TABLE IF NOT EXISTS `taxonomy_master` (
`product_id` int(10) NOT NULL,
`v_id` int(10) NOT NULL,
`vehicle_requirement` varchar(255) DEFAULT NULL,
`is_sellable` enum('True','False') DEFAULT 'True',
`programming_override` varchar(25) DEFAULT NULL,
PRIMARY KEY (`product_id`,`v_id`),
KEY `idx2` (`product_id`),
KEY `idx3` (`v_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS `vehicle_catalog` (
`v_id` int(10) NOT NULL,
`id` int(11) NOT NULL,
`v_make` varchar(255) NOT NULL,
`make_id` int(11) NOT NULL,
`v_model` varchar(255) NOT NULL,
`model_id` int(11) NOT NULL,
`v_year` varchar(255) NOT NULL,
PRIMARY KEY (`v_id`,`v_make`,`v_model`,`v_year`),
UNIQUE KEY `idx` (`v_make`,`v_model`,`v_year`),
UNIQUE KEY `idx2` (`v_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
Update: The successful query to get what I needed is here....
SELECT
m.id,COUNT(t.product_id) AS CountOf
FROM taxonomy_master t
INNER JOIN vehicle_catalog v ON t.v_id=v.id
INNER JOIN vehicle_make m ON v.make_id=m.id
GROUP BY m.id;
without the tables/columns this is my best guess from reverse engineering the given queries:
UPDATE m
SET product_count =COUNT(t.product_id)
FROM taxonomy_master t
INNER JOIN vehicle_catalog v ON t.v_id=v.id
INNER JOIN vehicle_make m ON v.make_id=m.id
GROUP BY m.name
The given code loops over each make, and then runs a query the counts for each. My answer just does them all in one query and should be a lot faster.
have an index for each of these:
vehicle_make.id cover on name
vehicle_catalog.id cover make_id
taxonomy_master.v_id
EDIT
give this a try:
CREATE TEMPORARY TABLE CountsOf (
id int(11) NOT NULL
, CountOf int(11) NOT NULL DEFAULT 0.00
);
INSERT INTO CountsOf
(id, CountOf )
SELECT
m.id,COUNT(t.product_id) AS CountOf
FROM taxonomy_master t
INNER JOIN vehicle_catalog v ON t.v_id=v.id
INNER JOIN vehicle_make m ON v.make_id=m.id
GROUP BY m.id;
UPDATE taxonomy_master,CountsOf
SET taxonomy_master.product_count=CountsOf.CountOf
WHERE taxonomy_master.id=CountsOf.id;
instead of using nested query ,
you can separated this query to 2 or 3 queries,
and in php insert the result of the inner query to the out query ,
its faster !
#haim-evgi Separating the queries will not increase the speed significantly, it will just shift the load from the DB server to the Web server and create overhead of moving data between the two servers.
I am not sure with the appropriate indexes you run such query 7 minutes. Could you please show the table structure of the tables involved in these queries.
Seems like you need the following indices:
INDEX BTREE('make_id') on vehicle_catalog
INDEX BTREE('v_id') on taxonomy_master