Query to order parent/child-hierachy - mysql

There's a table I have now:
I can't think of a query that would make the order of 'name' column that i need.
I need it to go like this:
ads->work_and_business->search_work->require_work->freelance->transport->cars->trucks->water->air->...
so, basically i need like parent->all children, next parent->all children
can someone help with this?
Edit: table create script:
CREATE TABLE categories (
id int(11) NOT NULL AUTO_INCREMENT,
level int(11) NOT NULL DEFAULT '1',
parent_category_id int(11) NOT NULL DEFAULT '1',
name varchar(255) DEFAULT NULL,
PRIMARY KEY (id),
KEY FK_categories_categories (parent_category_id)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8
Edit2: level is needed for something else in php part. in query part it's not needed

I tried with your sample data and i think this works
SELECT distinct(ifnull(c1.name,c.name)) as name
from categories c
right JOIN categories c1 ON c.id=c1.parent_category_id
order by c.parent_category_id;

Related

How to query records in appear in one table, but not in the other two tables

I have three tables: input, results, errors.
input table:
'input', 'CREATE TABLE `input` (\n `name` varchar(500) NOT NULL,\n PRIMARY KEY (`name`),\n UNIQUE KEY `domain_UNIQUE` (`name`)\n) ENGINE=InnoDB DEFAULT CHARSET=latin1'
The results table:
'results', 'CREATE TABLE `results` (\n `name` varchar(1000) NOT NULL,\n `no` varchar(500) DEFAULT NULL,\n `description` varchar(500) DEFAULT NULL,\n `version` varchar(500) DEFAULT NULL,\n `ext` longtext,\n PRIMARY KEY (`name`),\n UNIQUE KEY `domain_UNIQUE` (`name`)\n) ENGINE=InnoDB DEFAULT CHARSET=latin1'
The errors table:
'erros', 'CREATE TABLE `erros` (\n `error` varchar(500) DEFAULT NULL,\n `name` varchar(1000) NOT NULL,\n `code` longtext,\n PRIMARY KEY (`name`),\n UNIQUE KEY `ip_UNIQUE` (`name`)\n) ENGINE=InnoDB DEFAULT CHARSET=latin1'
I want to query the name field where exist in the input table, but not exists in the results and not in the errors tables.
I tried constructing the query using NOT IN, but it lasts forever and then mysql workbench crashes. Note that the name field in the errors and results tables is always a name that exist in the input, but with a fixed xxx prefix.
Here is my attempt:
select input.name
from myscheme.input, myscheme.results, myscheme.erros
where concat('xxx',input.name) not in (select results.name from myscheme.results)
and concat('xxx',input.name) not in (select erros.name from myscheme.erros);
Can you please help me query the name field where exist in the input but not in the results and not in the errors.
I would use not exists:
select i.name
from myschee.input i
where not exists (select 1 from myscheme.results r where r.name = concat('xxx', i.name)) and
not exists (select 1 from myscheme.errors e where e.name = concat('xxx', i.name));
Notes:
I don't know why you want to concatenate 'xxx' to the name, but presumably you have a reason.
The query is only selecting from one table, inputs, so that should be the only table in the FROM clause.
I strongly recommend NOT EXISTS over NOT IN, because NOT EXISTS works (as expected) even when the subquery returns NULL values.
I really don't understand the logic you are attempting in your WHERE clause. This seems like an AND condition with comparisons on the two tables.

MySQL query with multiple joins taking too long to execute

I have 3 tables. The first one is called map_life, the second one is called scripts and the third one is called npc_data.
I'm running the following query to get all the properties from map_life while also getting the script column from scripts and the storage_cost column from npc_data if the ids match.
SELECT life.*
, script.script
, npc.storage_cost
FROM map_life life
LEFT
JOIN scripts script
ON script.objectid = life.lifeid
AND script.script_type = 'npc'
LEFT
JOIN npc_data npc
ON npc.npcid = life.lifeid
As you can see, map_life id is lifeid, while scripts id is objectid and npc_data id is npcid.
This query is taking about 5 seconds to execute, and I have no idea why. Here's the CREATE statements for all those 3 tables, maybe I'm missing something?
CREATE TABLE `mcdb83`.`map_life` (
`id` bigint(21) unsigned NOT NULL AUTO_INCREMENT,
`mapid` int(11) NOT NULL,
`life_type` enum('npc','mob','reactor') NOT NULL,
`lifeid` int(11) NOT NULL,
`life_name` varchar(50) DEFAULT NULL COMMENT 'For reactors, specifies a handle so scripts may interact with them; for NPC/mob, this field is useless',
`x_pos` smallint(6) NOT NULL DEFAULT '0',
`y_pos` smallint(6) NOT NULL DEFAULT '0',
`foothold` smallint(6) NOT NULL DEFAULT '0',
`min_click_pos` smallint(6) NOT NULL DEFAULT '0',
`max_click_pos` smallint(6) NOT NULL DEFAULT '0',
`respawn_time` int(11) NOT NULL DEFAULT '0',
`flags` set('faces_left') NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `lifetype` (`mapid`,`life_type`)
) ENGINE=InnoDB AUTO_INCREMENT=32122 DEFAULT CHARSET=latin1;
CREATE TABLE `mcdb83`.`scripts` (
`script_type` enum('npc','reactor','quest','item','map_enter','map_first_enter') NOT NULL,
`helper` tinyint(3) NOT NULL DEFAULT '-1' COMMENT 'Represents the quest state for quests, and the index of the script for NPCs (NPCs may have multiple scripts).',
`objectid` int(11) NOT NULL DEFAULT '0',
`script` varchar(30) NOT NULL DEFAULT '',
PRIMARY KEY (`script_type`,`helper`,`objectid`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='Lists all the scripts that belong to NPCs/reactors/etc. ';
CREATE TABLE `mcdb83`.`npc_data` (
`npcid` int(11) NOT NULL,
`storage_cost` int(11) NOT NULL DEFAULT '0',
`flags` set('maple_tv','is_guild_rank') NOT NULL DEFAULT '',
PRIMARY KEY (`npcid`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
For this query:
SELECT l.*, s.script, npc.storage_cost
FROM map_life l LEFT JOIN
scripts s
ON s.objectid = l.lifeid AND
s.script_type = 'npc' LEFT JOIN
npc_data npc
ON npc.npcid = l.lifeid;
You want indexes on: scripts(object_id, script_type, script) and npc_data(npcid, storage_cost). The order of the columns in these indexes is important.
map_life.lifeid does not have any indexes defined, therefore the joins will result in full table scans. Define an index on map_life.lifeid field.
In scripts table the primary key is defined on the following fields in that order: script_type, helper, objectid. The join is done on objectid and there is a constant filter criterion on script_type. Because the order of the fields in the index is wrong, MySQL cannot use the primary key for this query. For this query the order of the fields in the index should b: objectid, script_type, helper.
The above will significantly speed up the joins. You may further increase the speed of the query if your indexes actually cover all fields that are in the query because in this case MySQL does not even have to touch the tables.
Consider adding an index with the following fields and order to the scripts table: object_id, script_type, script and npcid, storage_cost index to npc_data table. However, these indexes may slow down insert / update / delete statements, so do some performance testing before adding these indexes to production environment.

How can I delete a row that has only null value in each column?

I would like to know how can I delete a row that has only null values in each column.
CREATE TABLE taxes
(
id int(11) NOT NULL,
Name varchar(255) DEFAULT NULL,
Person varchar(255) DEFAULT NULL,
Price int(11) DEFAULT NULL,
Year varchar(255) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
This is my table. I haven't tried anything because I don't know what could cause this.
Actually, issue occurred after I altered a table in order to add another column.
After the column was added, an empty row appeared and if I try to modify that row, another one pops out.
Can anyone help me?
Thanks!
First try:
SELECT Id
FROM taxes
WHERE Name IS NULL
AND Person IS NULL
AND Price IS NULL
AND Year IS NULL;
If it returns affected rows, then use DELETE.
DELETE FROM taxes
WHERE Id IN (SELECT Id
FROM taxes
WHERE Name IS NULL
AND Person IS NULL
AND Price IS NULL
AND Year IS NULL);
OR
DELETE FROM taxes
WHERE Name IS NULL
AND Person IS NULL
AND Price IS NULL
AND Year IS NULL
You can COALESCE and then test if a row has all NULL values.
First, try this to test:
SELECT * FROM yourtable
WHERE COALESCE(column1,column2,column3) IS NULL
Then, if that returns everything you want, go ahead and DELETE:
DELETE FROM yourtable
WHERE COALESCE(column1,column2,column3) IS NULL
Yes. The SELECT * FROM table does show it's content. However, I managed to discover the thing that bothered me. I created two different tables, one with 'NOT NULL' and one with 'DEFAULT NULL'. I noticed that the table that contains 'NOT NULL' for columns does create an extra row full of 'NULL' values and the table that contains 'DEFAULT NULL' does not do that. Can anyone explain to me why? What's the difference beetween them?
Table 1 :CREATE TABLE test1 (
id int(11) unsigned NOT NULL,
Animal varchar(25) NOT NULL,
Size varchar(25) NOT NULL,
PRIMARY KEY (id)
);
Table 2: CREATE TABLE test2 (
id int(11) DEFAULT NULL,
NAME varchar(25) DEFAULT NULL,
CITY varchar(25) DEFAULT NULL
);

Creating a table with two different sorted columns

I have created the simple table in a MySQL database;
CREATE TABLE `opportunity` (
`customer` varchar(255) NOT NULL DEFAULT '',
`category` varchar(255) NOT NULL DEFAULT '',
`bill_amount` decimal(13,2) NOT NULL,
PRIMARY KEY (`bill_amount`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
I used 'bill_amount' as my primary key so I could remove duplicate information when I import data to the table, but I need to also need to separate records by separate categories as well. Here is an example of what I have, what results I am getting, and what I need. If anyone could give me advice on how to properly set up my table so it groups the data as need I would appreciate the help.

Order by two fields - Indexing

So I've got a table with all users, and their values. And I want to order them after how much "money" they got. The problem is that they have money in two seperate fields: users.money and users.bank.
So this is my table structure:
CREATE TABLE IF NOT EXISTS `users` (
`id` int(4) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(54) COLLATE utf8_swedish_ci NOT NULL,
`money` bigint(54) NOT NULL DEFAULT '10000',
`bank` bigint(54) NOT NULL DEFAULT '10000',
PRIMARY KEY (`id`),
KEY `users_all_money` (`money`,`bank`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_swedish_ci AUTO_INCREMENT=100 ;
And this is the query:
SELECT id, (money+bank) AS total FROM users FORCE INDEX (users_all_money) ORDER BY total DESC
Which works fine, but when I run EXPLAIN it shows "Using filesort", and I'm wondering if there is any way to optimize it?
Because you want to sort by a derived value (one that must be calculated for each row) MySQL can't use the index to help with the ordering.
The only solution that I can see would be to create an additional total_money or similar column and as you update money or bank update that value too. You could do this in your application code or it would be possible to do this in MySQL with triggers too if you wanted.