database table structure to store user location - mysql

I have a requirement to store user's proper location & send them newsletters as per them, I would like to understand the best way to store them as I have been finding it challenging to retrieve it after storing.
First of all, the address that needs to be stored is like:-
Country1-City1-SocietyName1-AnyMoreSmallLocation1-...so on.
So, now what I have done so far...
Table 1...
PID Place Parent
1 Country1 0
2 Country2 0
3 City1 1
4 City2 1
5 City3 2
6 Society1 3
n so on
Then
User table where I am keeping location with UID
UID Name PID
1. John 6
2. Sam 7
But at the get call of user location it needs to be like this...society name, city, country. which seems not good as per current design..please suggest.

If each user has only one adress, consider having only one table :
UID Name Country City etc.
But if there is multiple adresses per user, 2 tables (User and Adress):
UID Name
AdresseID UID Country City etc.

Related

List all teams and team member details in a subject

I'm having some trouble working out how to write a query. I want to be able to make a list of all teams, and the students within the team that are in a certain subject.
Here are the sorts of tables I have.
Team (teamID, teamName, subjectID)
Student(studentID, Student Name)
AssignTeam(AssignID, studentID, teamID)
Subject(subjectID, subjectName)
This is what I would like the output to look like.
Team 1 - Team Name
Student 1 ID - Student 1 Name
Student 2 ID - Student 2 Name
Student 3 ID - Student 3 Name
Student 4 ID - Student 4 Name
Team 2 - Team Name
Student 1 ID - Student 1 Name
Student 2 ID - Student 2 Name
Student 3 ID - Student 3 Name
Student 4 ID - Student 4 Name
Student 5 ID - Student 5 Name
Team 3 - Team Name
Student 1 ID - Student 1 Name
Student 2 ID - Student 2 Name
Student 3 ID - Student 3 Name
I'm struggling to work out how to format it in such a way to include the breaks between the groups themselves. I only really know how to make a list that looks like this
Group StuID StuName
-- ---- ----
1 1 Mike
1 2 Stacey
1 3 Jenny
2 4 Rick
2 5 Sam
3 6 Larry
3 4 Anita
I want to build the list using mySQL but it will ultimately be outputting via PHP. I was hoping to create a stored procedure which I can then call and pass the subjectID into which will then create the list.
I haven't quite worked out if the one procedure would create the list and convert to string for output or if that should be two separate queries.
Any suggestions would be much appreciated.
Thanks
This is not a mysql solution but would it not be simple enough to read the rows from mysql in PHP, and when the Group changes output the header line for that group?
See the snippet below. You'll have to make outputRow() and outputGroupHeader() generate the output in the format you need.
<?php
$lastgroup = "";
while ($row = mysqli_fetch_assoc($query))
{
if ($row['group'] != $lastgroup) {
outputGroupHeader($row['group']);
$lastgroup = $row['group'];
}
outputRow($row);
}

Define table of choosed user row in multiple table list

I have control dashboard where multiple tables are listed with query
And in dashboard I can switch it to one table from ALLData to User1Table... and vice versa.
When there is only one table chosed I can easily manipulate data. However, I am struggling with updating rows when ALLData(all tables) are listed in dashboard. I can update it checking each table. I was wondering is there any better way to update it.
Tables have no DR. All tables have same column names.
//ALLData
SELECT * FROM users1
UNION ALL
SELECT * FROM users2...
user1
id name tel status
1 Bob 911 1
user2
id name tel status
3 Anna 11 0
3 Jack 12 1
//ALLData in dashboard
id name tel status
1 Bob 911 1
3 Anna 11 0
3 Jack 12 1
I can use id and status as PK

how to design table for accessing the different places

The tables are for users to access different places
The design as below:
user table:
<user>
userid
username
place (the row define access rights)
place table:
<place>
placeid
placename
floor
My thoughts:
three places and placeid are 001,002,003
one user and userid is 001 to aceess these three places
<user>
userid username place
001 john 001,002,003
<place>
placeid placename floor
001 A 1
002 B 2
003 C 3
004 D 4
My question is,
in "user" table, the attribute "place" contains many placeids,
and separate by a comma, this design is fine or bad ?
It needs to separate the place values from "user" table ?
Using a comma delimited list to do a many to many relationship is bad design. You should use an intermediate table instead:
<user>
userid
username
<place>
placeid
placename
floor
<accessrights>
userid
placeid
Instead of putting "1,2,3" in user.place for userid 001, then, you put three rows in accessrights, all with userid 001 and one with each placeid.
That's not a good idea. Make a separate table to store the relationship:
<users-places>
userid placeid
1 1
1 2
1 3
Indexing your approach would not be straight forward - although possible.
Use the name "users-places" as it implies what 2 tables it relates. Change the name if you significantly store more information about this relationship - ie, you start adding columns to this new table.
Also, name your tables in the plural form. Singular is reserved for class names. Tables are thought of as collections.
Thank you all,
I modified my design as below, is it fine ?
<user>
userid username groupid
1 john 1
<group>
groupid groupname
1 admin
2 general
3 special
<group_manage>
groupno groupid placeid
1 1 1
2 1 2
3 1 3
4 1 4
5 2 1
6 2 2
7 2 3
<place>
placeid placename floor
1 A 1
2 B 2
3 C 3
4 D 4

Listing all rows that have a duplicate entry in a particular column in MySQL table

Despite a good deal of searching I haven't come up with the correct method of listing all columns for rows that have the same content in a particular column (let's say the column 'Name').
So if my table, called USERS, had the following content:
ID User Name
1 Nick Nick
2 NickP Nick
3 NickC Nick
4 John John
5 Brian Brian
The SELECT statement should return:
ID User Name
1 Nick Nick
2 NickP Nick
3 NickC Nick
As these are all the rows that contain the same content in column 'Name'. How would I write this?
How about this?
SELECT * FROM Users WHERE Name IN(SELECT Name FROM Users GROUP BY Name HAVING COUNT(1) > 1)

SQL "shortcut" identifiers or a long string of joins?

QUESTION: Is it okay to have "shortcut" identifiers in a table so that I don't have to do a long string of joins to get the information I need?
To understand what I'm talking about, I'm going to have to lay ouf an example here that looks pretty complicated but I've simplified the problem quite a bit here, and it should be easily understood (I hope).
The basic setup: A "company" can be an "affiliate", a "client" or both. Each "company" can have multiple "contacts", some of which can be "users" with log in privileges.
`Company` table
----------------------------------------------
ID Company_Name Address
-- ----------------------- -----------------
1 Acme, Inc. 101 Sierra Vista
2 Spacely Space Sprockets East Mars Colony
3 Cogswell Cogs West Mars Colony
4 Stark Industries Los Angeles, CA
We have four companies in our database.
`Affiliates` table
---------------------
ID Company_ID Price Sales
-- ---------- ----- -----
1 1 50 456
2 4 50 222
3 1 75 14
Each company can have multiple affiliate id's so that they can represent the products at different pricing levels to different markets.
Two of our companies are affiliates (Acme, Inc. and Stark Industries), and Acme has two affiliate ID's
`Clients` table
--------------------------------------
ID Company_ID Referring_affiliate_id
-- ---------- ----------------------
1 2 1
2 3 1
3 4 3
Each company can only be a client once.
Three of our companies are clients (Spacely Space Sprockets, Cogswell Cogs, and Stark Industries, who is also an affiliate)
In all three cases, they were referred to us by Acme, Inc., using one of their two affiliate ID's
`Contacts` table
-----------------------------------------
ID Name Email
-- -------------- ---------------------
1 Wylie Coyote wcoyote#acme.com
2 Cosmo Spacely boss#spacely.com
3 H. G. Cogswell ceo#cogs.com
4 Tony Stark tony#stark.com
5 Homer Simpson simpson#burnscorp.com
Each company has at least one contact, but in this table, there is no indication of which company each contact works for, and there's also an extra contact (#5). We'll get to that in a moment.
Each of these contacts may or may not have a login account on the system.
`Contacts_type` table
--------------------------------------
contact_id company_id contact_type
---------- ---------- --------------
1 1 Administrative
2 2 Administrative
3 3 Administrative
4 4 Administrative
5 1 Technical
4 2 Technical
Associates a contact with one or more companies.
Each contact is associated with a company, and in addition, contact 5 (Homer Simpson) is a technical contact for Acme, Inc, and contact 4 (Tony Stark) is a both an administrative contact for company 4 (Stark Industries) and a technical contact for company 3 (Cogswell Cogs)
`Users` table
-------------------------------------------------------------------------------------
ID contact_id company_id client_id affiliate_id user_id password access_level
-- ---------- ---------- --------- ------------ -------- -------- ------------
1 1 1 1 1 wylie A03BA951 2
2 2 2 2 NULL cosmo BF16DA77 3
3 3 3 3 NULL cogswell 39F56ACD 3
4 4 4 4 2 ironman DFA9301A 2
The users table is essentially a list of contacts that are allowed to login to the system.
Zero or one user per contact; one contact per user.
Contact 1 (Wylie Coyote) works for company 1 (Acme) and is a customer (1) and also an affiliate (1)
Contact 2 (Cosmo Spacely) works for company 2 (Spacely Space Sprockets) and is a customer (2) but not an affiliate
etc...
NOW finally onto the problem, if there is one...
Do I have a circular reference via the client_id and affiliate_id columns in the Users table? Is this a bad thing? I'm having a hard time wrapping my head around this.
When someone logs in, it checks their credentials against the users table and uses users.contact_id, users.client_id, and users.affiliate_id to do a quick look up rather than having to join together a string of tables to find out the same information. But this causes duplication of data.
Without client_id in the users table, I would have to find the following information out like this:
affiliate_id: join `users`.`contact_id` to `contacts_types`.`company_id` to `affiliates`.`company_id`
client_id: join `users`.`contact_id` to `contacts_types`.`company_id` to `clients`.`company_id`
company_id: join `users`.`contact_id` to `contacts_types`.`company_id` to `company`.`company_id`
user's name: join `users`.`contact_id` to `contacts_types`.`contact_id` to `contacts`.`contact_id` > `name`
In each case, I wouldn't necessarily know if the user even has an entry in the affiliate table or the clients table, because they likely have an entry in only one of those tables and not both.
Is it better to do these kinds of joins and thread through multiple tables to get the information I want, or is it better to have a "shortcut" field to get me the information I want?
I have a feeling that over all, this is overly complicated in some way, but I don't see how.
I'm using MySQL.
it's better to do the joins. you should only be denormalizing your data when you have timed evidence of a slow response.
having said that, there are various ways to reduce the amount of typing:
use "as" to give shorter names to your fields
create views. these are "virtual tables" that already have your standard joins built-in, so that you don't have to repeat that stuff every time.
use "with" in sql. this lets you define something like a view within a single query.
it's possible mysql doesn't support all the above - you'll need to check the docs [update: ok, recent mysql seems to support views, but not "with". so you can add views to do the work of affiliate_id, client_id etc and treat them just like tables in your queries, but keeping the underlying data nicely organised.]