custom made order by mysql - mysql

I have a row of entities stored in a mysql table;
entity table
order
id
name
type (refers to Type(id))
and a row of types stored in another table
Type table
id
name
order
the ORDER column in Type table specifies by what order the entities should be sorted - some should be ordered by name and some by id.
How do I create a mysql query that gets the ORDER BY clause from the type table and sorts the entities in the entity table by the ORDER stored for that entity type in the Type table
for example, let us say I have the following rows:
Entity table:
row 1:
id = 1
name = Virginia
type = 1
row 2:
id = 2
name = Virginia
type = 1
row 3:
id = 3
name = Canada
type = 2
types (rows in Type table)
row 1
id = 1
name = states
order = "name"
row 2:
id = 2
name = countries
order = id
I want to do the following query
SELECT entities.id, entities.name FROM entities INNER JOIN type ON entities.type = type.id ORDER BY ....
in the ORDER BY I want to order the entities based on what is stored in the ORDER row in the type table. So countries should be sorted by Entity(ID) and states should be sorted by Entity(name). How can I do that?

This doesn't seem like a very good design for a database. For your example, I would suggest something more similar to this:
CREATE TABLE countries (
countryID INT NOT NULL,
countryName VARCHAR(30)
);
CREATE TABLE states (
stateID INT NOT NULL,
countryID INT,
stateName VARCHAR(30)
);
Then you can perform queries like:
SELECT c.countryName, s.stateName
FROM countries c LEFT JOIN states s ON c.countryID = s.countryID
ORDER BY countryName, stateName;
At the very least, I would suggest using more obvious names for your columns, like in your entity table, you have a column named 'type' which refers to the 'id' field in the type table. Perhaps name them both typeID or something more obvious.
I also think it's a bad idea to create a column that stores information about which column to order by. Not only does that mean that you'll have to execute two queries every time (one to fetch the order by, and one to fetch the actual data), but you will also be storing a lot of extra data unnecessarily.

Related

querying values from several tables mysql

I have 4 tables containing id and names from different fields, and a master table that contains only ids, i need to create a query that return the names.
This is the structure (simplified)
table region = columns id, name
table country = columns id, name
table ethnics = columns id, name
table religion = columns id, name
table master = columns region, country,ethnics, religion
table master contains ONLY ids for each column, and i need to return the names that matches those ids, but i can't create the proper JOIN syntax.
Any hint?
Try this:
select region.name, country.name, ethnics.name, religion.name
from master
join region on (region.id = master.region)
join country on (country.id = master.country)
join ethnics on (ethnics.id = master.ethnics)
join religion on (religion.id = master.religion)
Then you can add any where clauses that you might need to filter the results.

Querying two tables with one query with replacing word

I have two tables in mySql like:
table 1: city
id name transport
1 new-york 1,3,4
2 dallas 3,4
3 la 1,2,4
4 california 3,4
table 2: transport
id name
1 bus
2 trolleybus
3 train
4 metro
Can I received result like example with one query?
result:
id name transport
1 new-york bus,train,metro
2 dallas train,metro
3 la bus,trolleybus,metro
4 california train,metro
You should change your database structure and normalize it. Never store data as comma-separation since its a bad way to store data. However till you fix the database design the following query should do what you are looking at.
select
id,
name,
group_concat(transport)
from
(
select
c.id,
c.name,
t.transport as transport
from city c
join transport t on find_in_set(t.id,c.transport)
)x
group by id ;
DEMO
If you need to order the transport values then you can use
group_concat(transport ORDER BY transport)
why is comma-separation is bad practice?
You can read the following why it should be ignored
Is storing a delimited list in a database column really that bad?
To normalize the database you will need to create another table as
city_transport (cid int , tid) ;
cid = city id
tid = transport id
For each city you will have multiple entry in this table. So the tables should look like
create table city (id int , name varchar(100));
insert into city values
(1,'new-york'),(2,'dallas'),(3,'la'),(4,'california');
create table transport (id int ,transport varchar(100));
insert into transport values
(1,'bus'),(2,'trolleybus'),(3,'train'),(4,'metro');
create table city_transport (cid int ,tid int);
insert into city_transport values
(1,1),(1,3),(1,4),(2,3),(2,4),(3,1),(3,2),(3,4),(4,3),(4,4);
And the query to get the same result is as
select
c.id,
c.name,
group_concat(t.transport order by t.transport) as transport
from city_transport ct
join city c on c.id = ct.cid
join transport t on t.id = ct.tid
group by c.id ;
When you have a large amount of data then essentially you will need index and then using join on indexed columns the performance will be way better than using find_in_set with comma separated list
You should work with a table between city and transport to be correct. That being said, you could fix this using REPLACE() and subqueries but the performance will be horrible.

Joining three tables in SQLite

I am writing an SQL query in order to fetch data, which is to be populated in the scrollable table .
Content id's of the contents which are going to be compared(Content1, Content2, Content3 .. in the image above) will be the input to the query.
Since, for comparison minimum 2 items are required, the number of id's passed to the query will always be 2 or greater than 2.
Following is the SQL of 3 tables, from which the required data is to be fetched.
Following table contains the Paramter names that are to be compared:
CREATE TABLE tbl_content_commons (
id integer PRIMARY KEY,
content_common_code char(20) NOT NULL,
content_common_name char(100) NOT NULL // The comparison label
)
Following table contains the code of comparison label(content_common_name char) in the table above and the Content id of the contents(which would be passed as the parameter for the query)
CREATE TABLE tbl_comparison_values (
id integer PRIMARY KEY,
tbl_content_common_id integer NOT NULL,// ID's of the Contents under comparison
userneed_comparison_label_id integer NOT NULL,// ID of comparison label in the table above
value char(50) NOT NULL// Value corresponding to a comparison label - if it exists for a given content id
)
Finally, the table containing the name of the contents(Content1, Content2..) whose id's were passed as parameters to the query
CREATE TABLE userneed_comparison_labels (
id integer PRIMARY KEY,
name char(50) NOT NULL// Name of the content whose id's are passed through queries. content ID in the table above
)
I have made enough of efforts in writing a query to fetch data that would help me populate the table shown in the attached image, but did not succeed. I can show the queries I have written, but since it again prolongs the question, I am not posting here.
Any guidance or help as to how to proceed, writing this SQL query would be much appreciated.
How about this...
select c.content_common_name,
l.name,
v.value
from userneed_comparison_labels l
left join tbl_comparison_values v on l.id = v.userneed_comparison_label_id
left join tbl_content_commons c on c.id = v.tbl_content_common_id
where c.id in (1, 2, 3)
See SQL Fiddle for more detail.
Choose SQLLite (SQL.js) version. Click cancel if it asks if you want to use WebSQL.

SELECT INTO multiple #variables MySQL

I wish to store the result of a SELECT statment into multiple variables.
I know that the result of this query will always return 6 ints from 6 different rows.
I have tried using the following code :
SELECT id INTO #photo1, #photo2, #photo3, #photo4, #photo5, #photo6
FROM album WHERE uploaded = #time AND scene_id = NEW.id;
album is a table.
uploaded is a field in album.
scene_id is a field in album.
id is the PRIMARY_KEY of album.
I have read that the number of variables must equal the number of fields. Which is obviously not the case in the above statement.
With this in mind, how would I overcome this problem?
This code is being used within a MySQL Trigger.
EDIT : Relevant Table schema as per request :
person -- name of table
id | approved -- id is PK
album -- name of table
id | uploaded | scene_id -- id is PK
Trigger is fired on change of approved from 0 to 1
You can join with the same table and ensure that each join will provide a new id, something like (eg. for two ids, but you will get the point):
SELECT a1.id, a2.id INTO #photo1, #photo2
FROM album a1
inner join album a2 on a2.scene=a1.scene and a2.upload=a1.upload and a2.id>a1.id
WHERE a1.uploaded = #time AND a1.scene_id = NEW.id;
See SqlFiddle for a complete sql and test case.

mysql database join based on a mapping

An abstraction of the problem is like this:
I have one table having a column called 'country'. the value stored are name of the country, e.g. US, UK..
I have another table having a column called 'country_code'. the value stored are numerical representations of the country, e.g. 12, 17...
how can I perform a join operation (e.g. inner join) based on these 2 tables? the difficulty is that the country and country_code has a one-to-one mapping but not directly equal to each other.
You could create a Mapping table containging the country and the country_code.
I assume you cannot change the table containing the country_code to use the string representation from country, or add an int column to your countries table?
Something like
country_mappings
country varchar column
country_code int column
PRIMARY KEY country, country_mapping
'
SELECT *
FROM countries c INNER JOIN
country_mappings cm ON c.country = cm.country inner join
your_other_table yot ON cm.country_code = yot.country_code