SQL Update one table comparing info from two tables - sql

I have the following problem:
Let's suppose I defined TWO tables
USERS
ID (int. key)
NAME (String)
SALARY (currency)
USERSADD
ID (int. key)
TYPE (String)
The 2nd table stores additional information for USERS. Obviously the real tables are more complicated but this is the idea. (Don't ask me why another table is created instead of adding fields to the first table, this is my boss's idea).
Now I am trying to UPDATE the first table if a condition from second table is satisfied.
Something like this:
UPDATE USERS U, USERSADD A
SET U.SALARY = 1000
WHERE U.ID = A.ID
AND A.TYPE = 'Manager'
In Netbeans Derby I have an error: ", found in column X", and it refers to the comma between the two tables (UPDATE USERS U, USERSADD A). I hope I was clear enough...
Would somebody be kind enough to provide me with a solution? Thanks in advance.

UPDATE USERS
SET SALARY = 1000
WHERE ID IN (
SELECT ID FROM USERSADD
WHERE TYPE = 'Manager')

UPDATE USERS
SET USERS.SALARY = 1000
FROM USERS JOIN USERSADD ON USERS.ID = USERSADD.ID
WHERE USERSADD.TYPE ='MANAGER'

The syntax you are using uses an implicit INNER JOIN. It would be better for you to use an explicit join. Try something like this:
UPDATE Users
SET Salary = 1000
FROM Users u
INNER JOIN Usersadd a on u.id=a.id
AND a.Type = 'Manager

UPDATE USERSU
SET SALARY = 1000
WHERE exist IN (
SELECT ID
FROM USERSADD A
WHERE TYPE = 'Manager'
AND U.id = A.id
)

Related

trouble with inner joining 2 tables

I have a database with 2 tables in it one is 'enlistments' and the other one is 'users'. In the enlistments table I have a user_id and in the users table I have a name. I want to get the name of the user which belongs to the id.
I know I need to do this with an inner join like this:
SELECT enlistments.round_id, users.name
FROM enlistments
INNER JOIN users
ON enlistments.user_id=users.name
WHERE enlistments.activity_id = 1;
However I get this error: Warning: #1292 Truncated incorrect DOUBLE value
I did some research and found out it has to do with comparing an int with a string but I don't know how to solve the problem.
This is how my database looks like
join on is the condition you use to join the tables. Here it's enlistments.user_id=users.id.
select e.round_id
,u.name
from enlistments e join users u on u.id = e.user_id
where activity_id = 1
round_id
name
1
test2
Fiddle
To validate and be sure you are pulling back the exact data desired, I usually provide aliases for each column brought back and make sure to bring back the join columns also. It's good practice to label where the columns returned originated.
SELECT
Enlistments.UserID as Enlistments_UserID,
Users.ID as Users_ID,
enlistments.round_id as Enlistments_RoundID,
users.name as Users_Name
FROM enlistments
INNER JOIN users
ON enlistments.user_id=users.id
WHERE enlistments.activity_id = 1;
SELECT EN.round_id, US.name
FROM enlistments EN
INNER JOIN users US
ON US.name= CAST(EN.user_id AS VARCHAR)
WHERE EN.activity_id = 1
What you are needing is the function cast that can convert any kind of data into another, so you'll pass your integer value as the first argument followed by "AS '%DATATYPE'" where %DATATYPE is the kind of data you want to achieve.
In your case:
SELECT CAST(123456 AS VARCHAR)
-- RETURNS : '123456'
Anyway, I’m not sure that you can be able to join these two tables with the join you are using.
For more help please share some data.

Field name from ID on table 1 but name on other table

This is a Firebird database.
First Table
Contacts Company_ID - job_title
Second Table
Client_id - Co_name
In contacts, I want to the job_title field to contain the co_name.
client_id and company_id are the same. Co_name correspond to company_id as well as client_id.
this:
UPDATE Contacts
SET Contacts.Job_title = Clients.co_name
where company_id in (
select client_id from clients
JOIN Contacts c ON Client_id=company_id where record_status='A')
gives me an error as cannot find (clients.co_name)
this other option:
UPDATE Contacts
JOIN Clients ON Clients.Client_id = Contacts.Client_id
SET Contacts.Job_title = Clients.Client_name
gives me an error on JOIN
Any other ideas please?
UPDATE Contacts
JOIN Clients ON Clients.Client_id = Contacts.Client_id
SET Contacts.Job_title = Clients.Client_name
To update a table from another source, you can use MERGE, which only works with Firebird 2.1 or higher:
merge into Contacts
using Clients
on Contacts.Company_ID = Clients.Client_id
when matched then update set Contacts.Job_title = Clients.co_name
Using UPDATE would be possible, but it would get ugly fast because of the lack of support for joined updates, the equivalent query would be something like the code below. I'm not sure if this will work in Firebird 1.5.
update Contacts
set Job_title = (select Clients.co_name from Client where Clients.Client_id = Contacts.Company_ID)
where exists (select * from Client where Clients.Client_id = Contacts.Company_ID)
This might be a bit inefficient because of the two sub-selects that are evaluated independently.

SQL Server View get count from related table where column = "True"

I have two related tables in SQL Server in a 1 to many relationship (Applicant, Reference).
I want a view that will retrieve all the data from the Applicant table and also add another column to the view that tells me how many related Reference rows there are where the "Complete" column is True.
Something like this using a subquery:
select applicantfield1, applicantfield2,
(select count(*) from
reference where reference.applicantkey = applicant.applicantkey
and reference.complete = 1) AS referencecount
from applicant
Unless the complete field is in the applicant table (not the reference table). If so, it would be more like this:
select applicantfield1, applicantfield2,
(select count(*) from
reference where
reference.applicantkey = applicant.applicantkey) AS referencecount
from applicant
where applicant.complete = 1
Something like the below. You need to join on a table. This will handle where the applicant also doesn't have a True reference.
SELECT A.*, isnull(r.comptotal,0) as CompleteTotal
FROM Applicant as a Left Join
(SELECT ApplicantId, Count(Complete) as comptotal
FROM Reference Where Complete=1 Group by ApplicantID) as r
on a.ApplicantId = r.applicantId

Creating a query that queries the data in a table more than once

I have a table of data of personal details of clients:
ID
name
addressID
referralID
Part of the data is a 'referralID'. This will be filled in for some entries if they have been referred by other clients in the database. Therefore the referralID will match up to an ID in the database.
I'm trying to create a query that will return the details of the referrers and the names of the people that they have referred e.g:
Referrals ID (Where referallID = ID),
Referrals name (name),
ID of client referred (ID),
Name of Client referred (name)
I'm having difficulty in how to approach this and what method to undertake as the query needs to reference itself in some way? How can i extract the details twice from the table?
Hope that is easy enough for someone to understand. Any help or guidance would be greatly appreciated, cheers
Replace MyTable with the name of your table and join to the same table using aliases:
SELECT
m.ID,
m.Name,
m.AddressID,
m2.name as ReferralName
FROM
MyTable m
INNER JOIN
MyTable m2
ON m2.ReferralID = m.ID
Assuming you want a list of all clients and the people they referred and that client is the table name and that ID=ReferallID...
Select * from client c1
LEFT join client c2 on C1.ID = C2.ReferallID

SQL - re-arrange a table via query

I have a poorly designed table that I inherited.
It looks like:
User Field Value
-------------------
1 name Aaron
1 email aaron#company.com
1 phone 800-555-4545
2 name Mike
2 email mike#group.org
2 phone 777-123-4567
(etc, etc)
I would love to extract this data via a query in the more sensible format:
User Name Email Phone
-------------------------------------------
1 Aaron aaron#company.com 800-555-4545
2 Mike mike#group.org 777-123-4567
I'm a SQL novice, but have tried several queries with variations of Group By,
all without anything even close to success.
Is there a SQL technique to make this easy?
this not a 'badly designed table'; but in fact an Entity Attribute Value (EAV) table. unfortunately, relational databases are poor platforms to implement such tables, and negate most of the nice things of RDBMS. A common case of using the wrong shovel to nail in a screw.
but i think this would work (based on Marcus Adams' answer, which i don't think would work (edit: now it does))
SELECT User1.Value AS name, User2.Value AS email, User3.Value AS phone
FROM Users User1
LEFT JOIN Users User2
ON User2.User = User1.User AND User2.Field='email'
LEFT JOIN Users User3
ON User3.User = User1.User AND User3.Field='phone'
WHERE User1.Field = 'name'
ORDER BY User1.User
Edit: got some niceties from other answers (LEFT Joins, and the field names on the ON clauses), now does anybody know how to put the remaining WHERE a little higher? (but not on the first JOIN's ON, that's too ugly), of course it doesn't matter since the query optimizer uglyfies it back anyway.
At my work we are unfortunate to have a database design like this. But this kind of design works better for us then a traditional database design because of the different records we have to store and gives us the flexibility that we need. The database that we are using stores millions of records.
This would be the fastest way to run the query on a large database using MSSQL. It saves from having to do as many joins which could be very costly.
DECLARE #Results TABLE
(
UserID INT
, Name VARCHAR(50)
, Email VARCHAR(50)
, Phone VARCHAR(50)
)
INSERT INTO #Results
SELECT DISTINCT User FROM UserValues
UPDATE
R
SET
R.Name = UV.Value
FROM
#Results R
INNER JOIN
UserValues UV
ON UV.User = R.UserID
WHERE
UV.Field = 'name'
UPDATE
R
SET
R.Email = UV.Value
FROM
#Results R
INNER JOIN
UserValues UV
ON UV.User = R.UserID
WHERE
UV.Field = 'Email'
UPDATE
R
SET
R.Phone = UV.Value
FROM
#Results R
INNER JOIN
UserValues UV
ON UV.User = R.UserID
WHERE
UV.Field = 'Phone'
SELECT * FROM #Results
You can use a self join:
SELECT User1.User, User1.Value as Name, User2.Value as Email,
User3.Value as Phone
FROM Users User1
JOIN Users User2
ON User2.User = User1.User
JOIN Users User3
ON User3.User = User1.User
WHERE User1.Field = 'name' AND User2.Field = 'email' AND User3.Field = 'phone'
ORDER BY User1.User
I tested this query, and it works.
I believe this will build the result set you're looking for. From there, you can create a view or use the data to populate a new table.
select user, name, email, phone from
(select user, value as name from table where field='name')
natural join
(select user, value as email from table where field='email')
natural join
(select user, value as phone from table where field='phone')
In MySQL you can do something like this:
SELECT
id,
group_concat(CASE WHEN field='name' THEN value ELSE NULL END) AS name,
group_concat(CASE WHEN field='phone' THEN value ELSE NULL END) AS phone,
...
FROM test
GROUP BY id
The aggregate function actually doesn't matter, as long as you have only one field of each type. You could also use min() or max() instead with the same effect.
A variant of Javier's answer, which has my vote.
SELECT
UserName.name, UserEmail.email, UserPhone.phone
FROM
Users AS UserName
INNER JOIN Users AS UserEmail ON UserName.User = UserEmail.User
AND UserName.field = 'name' AND UserEmail.field = 'email'
INNER JOIN Users AS UserPhone ON UserName.User = UserPhone.User
AND UserPhone.field = 'phone'
Use LEFT JOINs if not all attributes are guaranteed to exist. A composite index over (User,Field) would probably be beneficial for this.