I'm currently debugging a huge MySql call which joins a large amount of tables which share column names such as id, created_at, etc. I started picking it apart but I was wondering if there was a way to do something like:
SELECT * AS table.column_name FROM table1 LEFT JOIN etc etc etc...
In place of having to individually name columns like:
SELECT table1.`column2' AS 'NAME', table1.`column3` AS ...
It would definitely help with speeding up the debugging process if there's a way to do it.
Thanks.
Edit:
Thanks for the answers so far. They're not quite what i'm looking for and I think my question was a bit vague so i'll give an example:
Suppose you have this setup in your MySql Schema:
table: students
fields: INT id | INT school_id | VARCHAR name
table: schools
fields: INT id | INT name
students contains:
1 | 1 | "John Doe"
schools contains:
1 | "Imaginary School One"
Doing the MySql call "SELECT * FROM students LEFT JOIN schools ON (students.school_id = schools.id)" will yield:
id | school_id | name | id | name
1 | 1 | "John Doe" | 1 | "Imaginary School One"
We know better and we know that the first Id and Name columns refer to the students table and the second Id and Name refer to the schools table since the data set is really small and unambiguous with its naming. However, if we had to deal with a result set that contained multiple left joins and columns with similar names, then it would start to get difficult to read and normally you'd have to trace through it by following the joins. We could start doing something like
SELECT school.name AS 'school_name', etc etc etc...
But that gets incredibly impractical once you start dealing with large data sets.
I was wondering though if there was a way to return the result set wherein the column names would look like this instead:
students.id | students.school_id | students.name | schools.id | schools.name
Which would be useful for future references if I need to do something similar again.
What if you select the tables in order, and add a spacer column with the name.
i.e.
select 'table1', t1.*, 'table2', t2.*, 'table3', t3.*
...
At least that way you don't have to name specific columns.
you mean something like?
show tables;
desc <tablename>;
If you want to also return table names along with column names, you can use the CONCAT function.
EXAMPLE:
SELECT CONCAT('tableName', field) FROM tableNAme
Let us know if this is what you are looking for.
Why not use the same dot notation instead of the ambiguous underscores for separating your tables from column names. Just enclose the alias in back-ticks. For example:
SELECT students.id `students.id` FROM students;
Related
I have a table with the following columns: name - course1 - course2 - course3. Two rows look like this:
John - physics - math - art
Sara - math - chemistry - psychology
Now John has been expelled from the math class and I want to replace "math" with "none" on his row.
When I look for a solution I find things like this:
UPDATE tableName SET `course1` = 'none' WHERE `name`='John' AND `course1`='math';
That could be useful if I knew the column where 'math' was recorded for John. But that word can be under any column. What I need is something like this:
sql_query="find the row where name='John' and then find the column where we have the word 'math' and only there replace 'math' with 'none'.
Can you kindly help me with this?
In this case, I think there is no other way besides evaluating each column, like this:
update
my_table
set
course1 = if(course1 = 'math', 'none', course1),
course2 = if(course2 = 'math', 'none', course2),
course3 = if(course3 = 'math', 'none', course3)
where
name = 'John';
First of all, if your table i.e tbl_Student don't have an ID which is a Primary Key you are in big trouble, I am recommending you to have something like this, again I don't know what you are storing so keep in mind change it to what you need, but with a Primary Key:
please also note I have some changes for your table structure as well, I am starting with the simplest one
tbl_Student
--------------------
sid sName cName
--------------------
1 Shaho Math
2 Awat Physics
now, I want to change Shaho's cName to anything, in your case 'none' use this.
update tbl_Student set cName = 'none' where sid = '1'
because sid is a Primary Key you don't have to worry about duplicate here, since the Primary Key has two main characteristics Not Null and No Duplicate:
let me change some structure for you if you see in your provided example, the courses starts from One to unknown, might be two, or three or 10
you can do c1,c2,c3...c10, but it is not a good practice, since you are using a relational database, we can use that, let me show you an example:
tbl_Student
--------------------
sid sName
--------------------
1 Shaho
2 Awat
tbl_Course
--------------------
cid cName
--------------------
1 Math
2 Physics
here is the inner table
tbl_StudentCourse
--------------------
scid sid cid
--------------------
1 1 1
2 1 1
3 2 1
As you see you can have almost any course assigned to a specific student, but How I can get information for a student since they don't have a direct connection between tables?
well, we have one, the inner table tbl_StudentCourse which connects both of them, so, here we can use the join techniques to get whatever information we want, I want to select sid, sName, came for student one
SELECT tbl_student.sid, tbl_student.sName, tbl_course.cName from tbl_student left join tbl_studentcourse on (tbl_student.sid = tbl_studentcourse.sid) left join tbl_course on (tbl_course.cid = tbl_studentcourse.cid) where tbl_student.sid = 1
if you want all students:
SELECT tbl_student.sid, tbl_student.sName, tbl_course.cName from tbl_student left join tbl_studentcourse on (tbl_student.sid = tbl_studentcourse.sid) left join tbl_course on (tbl_course.cid = tbl_studentcourse.cid);
So, we are using this, why we don't use names or courses?
well, the answer for this is the process on string is much slower rather than the number, and you still might get duplicate values.
On the other hand, using a Key that is not null and not duplicated will change the entire game for us.
the other of using relational one is each student is now unique, each Course is now unique, you just assign which student has which course, also if you see just from looking, all other operation now is easier, do you want to update student name? then update it.
My advice is to use Relational, if you don't then go back to Excel just kidding.
I'm doing some volunteer work with Nepali refugees in my community and I am trying to organize their addresses. I have 656 Nepali last names in one table and about 608,000 addresses in another table. I have never used MySQL before and have only learned a little bit online to make these tables.
Not real names from table.
My tables:
AddressTable: 4 Columns
Owner_Name Owner_Address Owner_CityState Owner_Zip
------------------------------------------------------
Smith, John | ************* | *************** | *****
adhikari, Prem| ************* | *************** | *****
Baker, Mary | ************* | *************** | *****
NamesTable: 1 Column
Last_Name
-----------
Smith
adhikari
Baker
I only want the addresses for people who have Nepali last names, so I want to select all the columns from my AddressTable that match with the last names from my NamesTable by joining the tables from the Last_Name column in the NamesTable with the Owner_Name column in the AddressTable. Since the Owner_Name column has both last name and the first name I've been having trouble doing this.
Before I answer, let me just say that this is not going to work in all likelihood. Name matching like this is fraught with problems, unless you know that the data is canonically structured.
You can do this in several ways. The idea is that you need functions in the on clause. For instance:
select . . .
from addresstable a join
namestable n
on n.last_name = substring_index(owner_name, ',', 1);
This assumes that the last name is in the owner_name before the first comma.
I recommend using REGEXP here:
SELECT at.*
FROM AddressTable at
INNER JOIN NamesTable nt
ON at.Owner_Name REGEXP CONCAT('^', nt.Last_Name, ',');
Demo
As mentioned in previous above comments, a given last name by itself may not be unique. We can modify the above query to also check the first name, assuming that the names table contains that as well:
SELECT at.*
FROM AddressTable at
INNER JOIN NamesTable nt
ON at.Owner_Name REGEXP CONCAT('^', nt.Last_Name, ',') AND
at.Owner_Name REGEXP CONCAT(' ', nt.First_Name, '$');
But even this might still have problems, because sometimes people have first or last name consisting of two (or more) words. Also, such a thing as a middle name is possible.
For a better solution, you might want to break up the first, middle, and last names into separate columns before bringing your data into the database.
For example have url like domain.com/transport/cars
Based on the url want to select from mysql and show list of ads for cars
Want to choose fastest method (method that takes less time to show results and will use less resources).
Comparing 2 ways
First way
Mysql table transport with rows like
FirstLevSubcat | Text
---------------------------------
1 | Text1 car
2 | Text1xx lorry
1 | Text another car
FirstLevSubcat Type is int
Then another mysql table subcategories
Id | NameOfSubcat
---------------------------------
1 | cars
2 | lorries
3 | dogs
4 | flats
Query like
SELECT Text, AndSoOn FROM transport
WHERE
FirstLevSubcat = (SELECT Id FROM subcategories WHERE NameOfSubcat = `cars`)
Or instead of SELECT Id FROM subcategories get Id from xml file or from php array
Second way
Mysql table transport with rows like
FirstLevSubcat | Text
---------------------------------
cars | Text1 car
lorries | Text1xx lorry
cars | Text another car
FirstLevSubcat Type is varchar or char
And query simply
SELECT Text, AndSoOn FROM transport
WHERE FirstLevSubcat = `cars`
Please advice which way would use less resources and takes less time to show results. I read that better select where int than where varchar SQL SELECT speed int vs varchar
So as understand the First way would be better?
The first design is much better, because you separate two facts in your data:
There is a category 'cars'.
'Text1 car' is in the Category 'cars'.
Imagine, in your second design you enter another car, but type in 'cors' instead of 'cars'. The dbms doesn't see this, and so you have created another category with a single entry. (Well, in MySQL you could use an enum column instead to circumvent this issue, but this is not available in most other dbms. And anyhow, whenever you want to rename your category, say from 'cars' to 'vans', then you would have to change all existing records plus alter the table, instead of simply renaming the entry once in the subcategories table.)
So stay away from your second design.
As to Praveen Prasannan's comment on sub queries and joins: That is nonsense. Your query is straight forward and good. You want to select from transport where the category is the desired one. Perfect. There are two groups of persons who would prefer a join here:
Beginners who simply don't know better and always join from the start and try to sort things out in the end.
Experienced programmers who know that some dbms often handle joins better than sub-queries. But this is a pessimistic habit. Better write your queries such that they are easy to read and maintain, as you are already doing, and only change this in case grave performance issues occur.
Yup. As the SO link in your question suggests, int comparison is faster than character comparison and yield faster fetch. Keeping this in mind, first design would be considered as better design. However sub queries are never recommended. Use join instead.
eg:
SELECT t.Text, t.AndSoOn FROM transport t
INNER JOIN subcategories s ON s.ID = t.FirstLevSubcat
WHERE s.NameOfSubcat = 'cars'
I'm trying to select some data from a MySQL database.
I have a table containing business details, and a seperate one containing a list of trades. As we have multiple trades
business_details
id | business_name | trade_id | package_id
1 | Happy News | 12 | 1
This is the main table, contains the business name, the trade ID and the package ID
shop_trades
id | trade
1 | newsagents
This contains the trade type of the business
configuration_packages
id | name_of_trade_table
1 | shop_trades
2 | leisure_trades
This contains the name of the trade table to look in
So, basically, if I want to find the trade type (e.g., newsagent, fast food, etc) I look in the XXXX_trades table. But I first need to look up the name of XXXX from the configuration_packages table.
What I would normally do is 2 SQL queries:
SELECT business_details.*, configuration_packages.name_of_trade_table
FROM business_details, configuration_packages
WHERE business_details.package_id = configuration_packages.id
AND business_details.id = '1'
That gives me the name of the database table to look in for the trade name, so I look up the name of the table
SELECT trade FROM XXXX WHERE id='YYYY'
Where XXXX is the name of the table returned as part of the first query and YYYY is the id of the package, again returned from the first query.
Is there a way to combine these two queries so that I only run one?
I've used subqueries before, but only on the SELECT side of the query - not the FROM side.
Typically, this is handled by a union in a single query.
Normalization gets you to a logical model. This helps better understand the data. It is common to denormalize when implementing the model. Subtypes as you have here are commonly implemented in two ways:
Seperate tables as you have, which makes retrieval difficult. This results in your question about how to retreive the data.
A common table for all subtypes with a subtype indicator. This may result in columns which are always null for certain subtypes. It simplifies data access, and may alter the way that the subtypes are handled in code.
If the extra columns for a subtype are relatively rarely accessed, then you may use a hybrid implementation where the common columns are in the type table, and some or all of the subtype columns are in a subtype table. This is more complex to code.
That's not possible, and it sounds like a problem with your model.
Why don't you put shop_trades and leisure_traces into the same table with one column to distinct between the two?
If this is possible, try this
SELECT trade
FROM (SELECT 'TABLE_NAME' FROM 'INFORMATION_SCHEMA'.'TABLES'
WHERE 'TABLE_SCHEMA'='*schema name*')
WHERE id='YYYY'
UPDATE:
I think the code I have above is not possible. :|
I'm planing to build some database project.
One of the tables have a lot of attributes.
My question is: What is better, to divide the the class into 2 separate tables or put all of them into one table. below is an example
create table User { id, name, surname,... show_name, show_photos, ...)
or
create table User { id, name, surname,... )
create table UserPrivacy {usr_id, show_name, show_photos, ...)
The performance i suppose is similar due to i can use index.
It's best to put all the attributes in the same table.
If you start storing attribute names in a table, you're storing meta data in your database, which breaks first normal form.
Besides, keeping them all in the same table simplifies your queries.
Would you rather have:
SELECT show_photos FROM User WHERE user_id = 1
Or
SELECT up.show_photos FROM User u
LEFT JOIN UserPrivacy up USING(user_id)
WHERE u.user_id = 1
Joins are okay, but keep them for associating separate entities and 1->N relationships.
There is a limit to the number of columns, and only if you think you might hit that limit would you do anything else.
There are legitimate reasons for storing name value pairs in a separate table, but fear of adding columns isn't one of them. For example, creating a name value table might, in some circumstances, make it easier for you to query a list of attributes. However, most database engines, including PDO in PHP include reflection methods whereby you can easily get a list of columns for a table (attributes for an entity).
Also, please note that your id field on User should be user_id, not just id, unless you're using Ruby, which forces just id. 'user_id' is preferred because with just id, your joins look like this:
ON u.id = up.user_id
Which seems odd, and the preferred way is this:
ON u.user_id = up.user_id
or more simply:
USING(user_id)
Don't be afraid to 'add yet another attribute'. It's normal, and it's okay.
I'd say the 2 separate tables especially if you are using ORM. In most cases its best to have each table correspond to a particular object and have its field or "attributes" be things that are required to describe that object.
You don't need 'show_photos' to describe a User but you do need it to describe UserPrivacy.
You should consider splitting the table if all of the privacy attributes are nullable and will most probably have values of NULL.
This will help you to keep the main table smaller.
If the privacy attributes will mostly be filled, there is no point in splitting the table, as it will require extra JOINs to fetch the data.
Since this appears to be a one to one relationship, I would normally keep it all in one table unless:
You would be near the limit of the number of bytes that can be stored in a row - then you should split it out.
Or if you will normally be querying the main table separately and won't need those fields much of the time.
If some columns is (not identifiable or dependent on the primary key) or (values from a definite/fixed set is being used repeatedly) of the Table make a Different Table for those columns and maintain a one to one relationship.
Why not have a User table and Features table, e.g.:
create table User ( id int primary key, name varchar(255) ... )
create table Features (
user_id int,
feature varchar(50),
enabled bit,
primary key (user_id, feature)
)
Then the data in your Features table would look like:
| user_id | feature | enabled
| -------------------------------
| 291 | show_photos | 1
| -------------------------------
| 291 | show_name | 1
| -------------------------------
| 292 | show_photos | 0
| -------------------------------
| 293 | show_name | 0
I would suggest something differnet. It seems likely that in the future you will be asked for 'yet another attribute' to manage. Rather than add a column, you could just add a row to an attributes table:
TABLE Attribute
(
ID
Name
)
TABLE User
(
ID
...
)
TABLE UserAttributes
(
UserID FK Users.ID
Attribute FK Attributes.ID
Value...
)
Good comments from everyone. I should have been clearer in my response.
We do this quite a bit to handle special-cases where customers ask us to tailor our site for them in some way. We never 'pivot' the NVP's into columns in a query - we're always querying "should I do this here?" by looking for a specific attribute listed for a customer. If it is there, that's a 'true'. So rather than having these be a ton of boolean-columns, most of which would be false or NULL for most customers, AND the tendency for these features to grow in number, this works well for us.