Tough SQL Update - sql

2 databases QF AND TK
QF has the following:
Imagine you have a table called FunctionalGroup with this data:
FunctionalGroupID | FunctionalGroup
1 Engineering
2 Purchasing
And a table that was a set of login's with a functionalgroupID to reference the group the person is in...
LoginID | FunctionalGroupID | Login
1 1 Jon
2 1 Joe
3 2 Jane
So Jon and Joe are engineering while Jane is purchasing..simple enough
Now there is another database TK.
TK has the following table Login with something to this effect:
Login | FunctionalGroupID
Jon Purchasing
Joe Purchasing
Jane Purchasing
Notice how Jon and Joe in this database are now part of the purchasing group...But notice how this field is the text field and no ID. So what I want to do is use this table as the master data source and update the QF table such that the logins table from the QF now looks like this:
LoginID | FunctionalGroupID | Login
1 2 Jon
2 2 Joe
3 2 Jane
That is update this table to make Jon and Joe part of the purchasing group by setting their functionalgroupid = 2. Because 2 means purchasing.
I tried this:
UPDATE
Login
SET Login.FunctionalGroupID = FunctionalGroup.FunctionalGroupID
FROM Login INNER JOIN
TKKCommonData.dbo.Login lz
ON lz.Login = Login.Login
AND lz.FunctionalGroupID = FunctionalGroup.FunctionalGroup
But I get an error:
Msg 4104, Level 16, State 1, Line 1
The multi-part identifier "FunctionalGroup.FunctionalGroup" could not be bound.
This seems so easy but Im just not sure how to write the update statement. Im just looking to join the tables by the Login (which is the users name) and then by the Functionalgroup names.
I even tried this EDIT per Jay's answer with same error message
UPDATE
QuikFix.dbo.Login
SET QuikFix.dbo.Login.FunctionalGroupID = QuikFix.dbo.FunctionalGroup.FunctionalGroupID
FROM QuikFix.dbo.Login INNER JOIN
TKKCommonData.dbo.Login
ON TKKCommonData.dbo.Login.Login = QuikFix.dbo.Login.Login
AND TKKCommonData.dbo.Login.FunctionalGroupID = QuikFix.dbo.FunctionalGroup.FunctionalGroup
WHERE TKKCommonData.dbo.Login.LoginID= 101

You need an additional INNER JOIN:
UPDATE Login
SET
Login.FunctionalGroupID = FunctionalGroup.FunctionalGroupID
FROM Login
INNER JOIN TKKCommonData.dbo.Login lz
ON lz.Login = Login.Login
INNER JOIN FunctionalGroup
ON lz.FunctionalGroupID = FunctionalGroup.FunctionalGroup

Specify the database name for all of the tables in your query instead of just TKKCommonData.dbo.Login, seems like it can't find the FunctionalGroup table in the database the query is running against.

Related

Get value of one column based on another column in same table

Here is what I am trying to do: Get all people with the same boss and email the boss. I can only use the table below and I would like to add another column showing the boss email which is found in the table.
id name email boss
-------------------------------------------
1 Apple Apple#alo.com Rita
2 Bob Bob#alo.com Rita
3 Charlie Charlie#alo.com Nuna
4 Dan Dan#alo.com Rita
5 Rita Rita#alo.com Sheeba
6 Nuna Nuna#alo.com Sheeba
Thanks for any help.
You use a join to do that. It looks like the code below. When joining to the same table you have to use an alias.
SELECT base.name, boss.email as boss_email
from the_table_name_you_did_not_say as base
join the_table_name_you_did_not_say as boss on base.boss = boss.name
Technically you don't have to use an alias on the base table if you select a wildcard * for some platforms

SQL - Tracking student exam records as they move between schools

I'd like to pick some of your glorious minds for an optimal solution to my dilemma.
Scenario:
Schools have children and children take tests.
The tests point to the child, not the school.
If the child moves school, the test records are taken to the new school and the previous school has no record of the test being done as they are linked to the child.
Obviously, this isn't ideal and is the result of the database not being designed with this in mind. What would the correct course of action be; I’ve currently identified the 3 possibilities listed below which would solve the current problem. However, i cannot be sure which is best for the issue at hand - and if any better solutions exist.
Have each test store the school & student within the test records (requiring current records to be updated & increasing the size of the database)
Create a new child record, duplicating the existing data for the new school with a new ID so the test remains linked to the previous school (complicating the ability to identify previous test scores)
Separately keep track of moves to other schools, then use this additional table to identify current and previous using the timestamps (increased complexity and computational requirements)
EDIT:
So i tried to use a basic example, but requests for the task at hand have been requested.
Here's the DB Schema for the tables (simplified for problem, note: Postnatal is not important):
Patients: ID, MidwifeID, TeamID
Midwives: ID
Groups: ID
GroupsMidwives: MidwifeID, GroupsID
PatientObservations: ID, MidwifeID, PatientID
Using a query as follows:
SELECT Some Information
from Postnatals
JOIN Midwives on Postnatals.MidwifeID = Midwives.ID
JOIN Patients on Patients.PatientID = Postnatals.PatientID
JOIN GroupsMidwives on GroupsMidwives.MidwifeID = Midwives.ID
JOIN Groups on Groups.ID = GroupsMidwives.GroupID
JOIN PatientObservations on PatientObservations.PatientID =
Postnatals.PatientID
WHERE groups.Name = ?
*some extra checks*
GROUP BY Midwives.Firstname, Midwives.Surname, Midwives.ID
However, in the event that a midwife is moved to a different team, the data associated with the previous team is now owned by the newly assigned team. As described in the example detailed previously.
Thus a modification (which modification is yet to be realised) is required to make the data submitted - prior to a team change - assigned to the previous team, as of current, because of the way the records are owned by the midwife, this is not possible.
You should below suggestion as per you concern.
Step 1 ) You need to create School Master Table
ID | School | IsActive
1 | ABC | 1
2 | XYZ | 1
Step 2 ) You need to create Children Master having school id as foreign key
ID | School | Children Name| IsActive
1 | 2 | Mak | 1
2 | 2 | Jak | 1
Step 3 ) You need to create test table having children id as foreign key
ID | Children_id | Test Name | IsActive
1 | 2 | Math | 1
2 | 2 | Eng | 1
Now whenever child moves school then make child record inactive and create another active record with new school. This will help you to bifurcate the old test and new test.
do let me know in case morehelp required

Get data using JOIN

I have two tables having following data-
Social_Tbl
ID Name Value
------------------------
1 Facebook FB
2 Orkut OR
3 Google GL
4 Other OT
And Organization_tbl
ID Organization Name
-----------------------------
1 1234 Facebook
2 1234 Google
3 146 Other
4 126 Other
5 126 Facebook
6 77 Google
Here, 'Name' is the foreign key (Not ID).
I want to join these tables and get the 'Name' columns data which does not belong to organization id 1234. As follows-
Name
----
Orkut
Other
Here, 'Orkut' and 'Other' does not belong to 1234 organization.
I tried following query for this-
select * from Social_Tbl st
join Organization_tbl ot
on st.Name = ot.Name
where Organization = 1234
This query fetches Names related to 1234 i.e Facebook and Google. I want result
Orkut and Other. If I replace Organization = 1234 with Organization != 1234 it returns all data from Organization_tbl.
Can somebody help me on this. This should be pretty simple, just npt able to find it out.
Could be done with a subquery:
select st.Name
from Social_Tbl st
where not exists (
select *
from Organization_tbl ot
where st.Name = ot.Name
and ot.Organization = 1234
)
(This also returns names that don't have an entry in Organization_tbl at all.)

Check if a value exists in the child-parent tree

I'm creating a simple directory listing page where you can specify what kind of thing you want to list in the directory e.g. a person or a company.
Each user has an UserTypeID and there is a dbo.UserType lookup table. The dbo.UserType lookup table is like this:
UserTypeID | UserTypeParentID | Name
1 NULL Person
2 NULL Company
3 2 IT
4 3 Accounting Software
In the dbo.Users table we have records like this:
UserID | UserTypeID | Name
1 1 Jenny Smith
2 1 Malcolm Brown
3 2 Wall Mart
4 3 Microsoft
5 4 Sage
My SQL (so far) is very simple: (excuse the pseudo-code style)
DECLARE #UserTypeID int
SELECT
*
FROM
dbo.Users u
INNER JOIN
dbo.UserType ut
WHERE
ut.UserTypeID = #UserTypeID
The problem is here is that when people want to search for companies they will enter in '2' as the UserTypeID. But both Microsoft and Sage won't show up because their UserTypeIDs are 3 and 4 respectively. But its the final UserTypeParentID which tells me that they're both Companies.
How could I rewrite the SQL to ask it to return to return records where the UserTypeID = #UserTypeID or where its final UserTypeParentID is also equal to #UserTypeID. Or am I going about this the wrong way?
Schema Change
I would suggest you to break it down this schema a little bit more, to make your queries and life simpler, with this current schema you will end up writing a recursive query every time you want to get simplest data from your Users table, and trust me you dont want to do this to yourself.
I would break down this schema of these tables as follow:
dbo.Users
UserID | UserName
1 | Jenny
2 | Microsoft
3 | Sage
dbo.UserTypes_Type
TypeID | TypeName
1 | Person
2 | IT
3 | Compnay
4 | Accounting Software
dbo.UserTypes
UserID | TypeID
1 | 1
2 | 2
2 | 3
3 | 2
3 | 3
3 | 4
You say that you are "creating" this - excellent because you have the opportunity to reconsider your whole approach.
Dealing with hierarchical data in a relational database is problematic because it is not designed for it - the model you choose to represent it will have a huge impact on the performance and ease of construction of your queries.
You have opted for an Adjacently List model which is great for inserts (and deletes) but a bugger for selects because the query has to effectively reconstruct the hierarchy path. By the way an Adjacency List is the model almost everyone goes for on their first attempt.
Everything is a trade off so you should decide what queries will be most common - selects (and updates) or inserts (and deletes). See this question for starters. Also, since SQL Server 2008, there is a native HeirachyID datatype (see this) which may be of assistance.
Of course, you could store your data in an XML file (in SQL Server or not) which is designed for hierarchical data.

Using different columns values twice in a single SQL query?

I have a mySQL table called "User" containing multiple mixed values as this:
[user_id] [user_email] [birthday]
---------------------------------
1 x#xxx.com 01/01/1981
2 y#yyy.com 02/02/1982
3 z#zzz.com 03/03/1983
I have another table called "Name" which contains name of the user, but also of some movies like this:
[node_id] [name] [user_id]
----------------------------------
9 John Doe 1
10 Star Wars 90
11 Mike Smith 2
12 Mary Lord 3
13 Rocky III 91
Finally, I have a third table named "Vote" with which is a relationship between a user and some movies he likes.
[vote_id] [node_id] [user_id]
------------------------------
1 10 1
2 10 2
3 13 1
12 10 3
13 13 2
What I'm struggling to do is pull a query with twice the "name" value for two separate things: the name of the user, and the name of the movie he likes. Like this:
[user_id] [user_name] [Birthday] [movie_name]
-------------------------------------------------
1 John Doe 01/01/1981 Star Wars
2 Mike Smith 02/02/1982 Star Wars
1 John Doe 01/01/1981 Rocky III
3 Mary Lord 03/03/1983 Rocky III
2 Mike Smith 02/02/1982 Rocky III
SELECT user.id,
node.name,
user.birthday,
IF(node.type = "movie", node.name, "")
FROM user,
node
JOIN vote ON vote.user_id = user.user_id
WHERE user.id = node.id
I think I'm all mixed up... anyone can help please?
Assuming your schema is exactly what you posted above this should work verbatim.
Query
SELECT user.user_id,
node.name user_name,
user.birthday,
(select node.name from node where node_id = vote.node_id) as movie_name
FROM user
JOIN node ON user.user_id = node.user_id
JOIN vote ON vote.user_id = user.user_id
Result
You have got the database structure wrong. Store the user name in your first table "User"
I would strongly suggest that you store the user_name in the users table. With that change you can then have a much more simple query and a properly normalized schema.
New proposed schema.
users table
(Added user_name column)
[user_id][name][user_email][birthday]
1 name1 x#xxx.com 01/01/1981
2 name2 y#yyy.com 02/02/1982
3 name3 z#zzz.com 03/03/1983
nodes table (call this movies)
(removed user entries and the user_id column as you'll be using votes to link these to users)
[node_id] [name]
10 Star Wars
11 Mike Smith
12 Mary Lord
13 Rocky III
votes table (call this something like movies_users)
(removed the vote_id column as it's just a join table)
[node_id] [user_id]
10 1
10 2
13 1
10 3
13 2
Then your query should look something like this:
select users.user_id, users.name, users.birthday, nodes.name as movie_name
from users
join votes on users.id = votes.user_id
join nodes on votes.node_id = nodes.node_id
select user_id,user_name,birthday,name
from user,name,vote
where (and here you do all the joins like user_id from one table equals user_id from another table)
But here we have a problem which makes me impossible to understand how to write the correct code you have 2 fields in two different tables, user_name and name, you want to join the tables by this name? I don't understand.) I think you are mixing the movie names with the user names, reformulate the question please
I agree with the other answers that you would be better off if you moved the user name into the user table. However, if you are stuck with your current table structure, try this:
SELECT user.id,
uname.name user_name,
user.birthday,
movie.name movie_name
FROM user
JOIN node uname ON uname.user_id = user.user_id
JOIN vote ON vote.user_id = user.user_id
JOIN node movie ON vote.node_id = movie.id
(Assuming votes can only be cast for Movies, it should be unnecessary to blank out non-movies as these should never exist.)