I'm trying to create a stored procedure that will retrieve a table (called CommsLog) and match it to a user table to return all the names that are associated with it.
The user database stores all the users by alias and then I am trying to look up their first and last name in the database, concatenate them and return that into my results
This is what I've got at the moment but it only returns part of the table and the same names for both columns (These should be different)
SELECT
CommsLog.ID,
CommsLog.CommType,
CommsLog.Date,
Users.FirstName +' ' + Users.LastName,
Users.FirstName +' ' + Users.LastName,
CommsLog.Version
FROM CommsLog
INNER JOIN Users
ON CommsLog.SentTo=Users.Alias and CommsLog.SentFrom=.Users.Alias
EDIT: Update with Data and output
CommsLog table looks like:
+----+----------+--------------------------+----------+----------+---------+
| ID | CommType | Date | SentTo | SentFrom | Version |
+----+----------+--------------------------+----------+----------+---------+
| 12 | Test | 2014-12-19 09:38:10.000 | uk\tmot | uk\gmab | 1.10 |
+----+----------+--------------------------+----------+----------+---------+
User table looks like:
+---------+-----------+----------+------------+----------------------------------+
| Alias | FirstName | LastName | Telephone | email |
+---------+-----------+----------+------------+----------------------------------+
| uk\tmot | Tom | motoll | 0731424523 | tom.motoll#stackoverflow.com |
| uk\gmab | Grant | maberick | 0756463345 | grant.maberick#stackoverflow.com |
+---------+-----------+----------+------------+----------------------------------+
Ouput:
+----+----------+-------------------------+------------+----------------+---------+
| ID | CommType | Date | SentTo | SentFrom | Version |
+----+----------+-------------------------+------------+----------------+---------+
| 12 | Test | 2014-12-19 09:38:10.000 | Tom motoll | Grant maberick | 1.10 |
+----+----------+-------------------------+------------+----------------+---------+
It looks to me like you're trying to pull in both the names of the SentTo users as well as the names of the SentFrom users in your SELECT statement. If that's the case, then you're actually going to need to join your USERS table into your query twice, with aliases -- once for your SentTo users and once for your SentFrom users. Try this for a query, instead:
SELECT
CSLL.CommsLog.ID,
CSLL.CommsLog.CommType,
CSLL.CommsLog.Date,
UserTo.FirstName +' ' + UserTo.LastName,
UserFrom.FirstName +' ' + UserFrom.LastName,
CSLL.CommsLog.Version
FROM CSLL.CommsLog
INNER JOIN CSLL.Users UserTo ON CSLL.CommsLog.SentTo=UserTo.Alias
INNER JOIN CSLL.Users UserFrom ON CSLL.CommsLog.SentFrom=UserFrom.Alias
Since you didn't post your table structure or any sample data, you may need to tweak that query a bit to make it work, but it should at least get you close to what you're after.
Are you meaning to only get records that were sent from a user to themselves?
That is what your join condition is doing.
Related
I'm struggling to find a value that might be in different tables but using UNION is a pain as there are a lot of tables.
[Different table that contains the suffixes from the TestTable_]
| ID | Name|
| -------- | -----------|
| 1 | TestTable1 |
| 2 | TestTable2 |
| 3 | TestTable3 |
| 4 | TestTable4 |
TestTable1 content:
| id | Name | q1 | a1 |
| -------- | ---------------------------------------- |
| 1 | goose | withFeather? |featherID |
| 2 | rooster| withoutFeather?|shinyfeatherID |
| 3 | rooster| age | 20 |
TestTable2 content:
| id | Name | q1 | a1 |
| -------- | ---------------------------------------------------|
| 1 | brazilian_goose | withFeather? |featherID |
| 2 | annoying_rooster | withoutFeather?|shinyfeatherID |
| 3 | annoying_rooster | no_legs? |dead |
TestTable3 content:
| id | Name | q1 | a1 |
| -------- | ---------------------------------------- |
| 1 | goose | withFeather? |featherID |
| 2 | rooster| withoutFeather?|shinyfeatherID |
| 3 | rooster| age | 15 |
Common columns: q1 and a1
Is there a way to parse through all of them to lookup for a specific value without using UNION because some of them might have different columns?
Something like: check if "q1='age'" exists in all those tables (from 1 to 50)
Select q1,*
from (something)
where q1 exists in (TestTable_*)... or something like that.
If not possible, not a problem.
You could use dynamic SQL but something I do in situations like this where I have a list of tables that I want to quickly perform the same actions on is to either use a spreadsheet to paste the list of tables into and type a query into the cell with something like #table then use the substitute function to replace it.
Alternative I just paste the list into SSMS and use SHIFT+ALT+ArrowKey to select the column and start typing stuff out.
So here is my list of tables
Then I use that key combo. As you can see my cursor has now selected all those rows.
Now I can start typing and all rows selected will get the input.
Then I just go to the other side of the table names and repeat the action
It's not a perfect solution but it's quick a quick and dirty way of doing something repetitive quickly.
If you want to find all the tables with that column name you can use information schema.
Select table_name from INFORMATION_SCHEMA.COLUMNS where COLUMN_NAME = 'q1'
Given the type of solution you are after I can offer a method that I've had to use on legacy systems.
You can query sys.columns for the name of the column(s) you need to find in N tables and join using object_id to sys.tables where type='U'. This will give you a list of table names.
From this list you can then build a working query for each table, and depending on your requirements (is this ad-hoc?) either just manually execute it yourself of build a procedure that will do it for you using sp_executesql
Eg
select t.name, c.name
into #workingtable
from sys.columns c
join sys.tables t on t.object_id=c.object_id
where c.name in .....
psudocode:
begin loop while rows exist in #working table
select top 1 row from #workingtable
set #sql=your query specific to that table and column(s)
exec(#sql) / sp_executesql / try/catch as necessary
delete row from working table
end loop
Hopefully that give ideas at least for how you might implement your requirements.
I want to join tables in MS Access in such a way that it fetches only the latest record from one of the tables. I've looked at the other solutions available on the site, but discovered that they only work for other versions of SQL. Here is a simplified version of my data:
PatientInfo Table:
+-----+------+
| ID | Name |
+-----+------+
| 1 | John |
| 2 | Tom |
| 3 | Anna |
+-----+------+
Appointments Table
+----+-----------+
| ID | Date |
+----+-----------+
| 1 | 5/5/2001 |
| 1 | 10/5/2012 |
| 1 | 4/20/2018 |
| 2 | 4/5/1999 |
| 2 | 8/8/2010 |
| 2 | 4/9/1982 |
| 3 | 7/3/1997 |
| 3 | 6/4/2015 |
| 3 | 3/4/2017 |
+----+-----------+
And here is a simplified version of the results that I need after the join:
+----+------+------------+
| ID | Name | Date |
+----+------+------------+
| 1 | John | 4/20/2018 |
| 2 | Tom | 8/8/2010 |
| 3 | Anna | 3/4/2017 |
+----+------+------------+
Thanks in advance for reading and for your help.
You can use aggregation and JOIN:
select pi.id, pi.name, max(a.date)
from appointments as a inner join
patientinfo as pi
on a.id = pi.id
group by pi.id, pi.name;
something like this:
select P.ID, P.name, max(A.Date) as Dt
from PatientInfo P inner join Appointments A
on P.ID=A.ID
group by P.ID, P.name
Both Bing and Gordon's answers work if your summary table only needs one field (the Max(Date)) but gets more tricky if you also want to report other fields from the joined table, since you would need to include them either as an aggregated field or group by them as well.
Eg if you want your summary to also include the assessment they were given at their last appointment, GROUP BY is not the way to go.
A more versatile structure may be something like
SELECT Patient.ID, Patient.Name, Appointment.Date, Appointment.Assessment
FROM Patient INNER JOIN Appointment ON Patient.ID=Appointment.ID
WHERE Appointment.Date = (SELECT Max(Appointment.Date) FROM Appointment WHERE Appointment.ID = Patient.ID)
;
As an aside, you may want to think whether you should use a field named 'ID' to refer to the ID of another table (in this case, the Apppintment.ID field refers to the Patient.ID). You may make your db more readable if you leave the 'ID' field as an identifier specific to that table and refer to that field in other tables as OtherTableID or similar, ie PatientID in this case. Or go all the way and include the name of the actual table in its own ID field.
Edited after comment:
Not quite sure why it would crash. I just ran an equivalent query on 2 tables I have which are about 10,000 records each and it was pretty instanteneous. Are your ID fields (i) unique numbers and (ii) indexed?
Another structure which should do the same thing (adapted for your field names and assuming that there is an ID field in Appointments which is unique) would be something like:
SELECT PatientInfo.UID, PatientInfo.Name, Appointments.StartDateTime, Appointments.Assessment
FROM PatientInfo INNER JOIN Appointments ON PatientInfo_UID = Appointments.PatientFID
WHERE Appointments.ID = (SELECT TOP 1 ID FROM Appointments WHERE Appointments.PatientFID = PatientInfo_UID ORDER BY StartDateTime DESC)
;
But that is starting to look a bit contrived. On my data they both produce the same result (as they should!) and are both almost instantaneous.
Always difficult to troubleshoot Access when it crashes - I guess you see no error codes or similar? Is this against a native .accdb database or another server?
I'm very new to SQL/LINQ and could really use your help.
I have 3 tables:
Invitation table
| InviteId | Name | Email | SalesAgentId | |
|----------|----------|--------------|--------------|---|
| 9 | John Doe | john#doe.com | 1 | |
SalesAgent table
| SalesAgentId | UserId | Active |
|--------------|--------|--------------|
| 1 | 2 | true |
User table
| UserId | Name | Email |
|--------|--------------------------------------|-----------------------------------|
| 2 | Sales Guy | sales#agent.com |
Trying to generate a list of a given SalesAgent that should contain that SalesAgent's info along with info of the user that has been invited by the sales agent (from the Invitation table)
Goal:
Trying to Get a list of users (both from the Invitation table and User table that are tied to the SalesAgent Id (either the user is the sales agent himself, or the user was invited by the sales agent).
So in this scenario, the goal is to get the result table (result) as:
ResultId: If there is a record in User table, then use the SalesAgentId, but if the record is coming from Invitation table, then use the InviteId for this column.
Name/Email: Same logic; if record is in User table, use the Name/Email from User table, if not, then use the info from Invitation table.
InvitedUser: If record is in User table, then this should be false, but if its coming from Invitation table, then this should be true.
| ResultId | Name | Email | InvitedUser |
|----------|-----------|-----------------|-------------|
| 1 | Sales Guy | sales#agent.com | false |
| 9 | John Doe | john#doe.com | true |
I'm not sure what kind of join would help me in this scenario, more or less I need to combine results from 2 queries (I think). Ultimate goal is to get a linq query version of this select, but I think LINQ/EfCore doesn't support Concat when using different data stores.
I'd really appreciate any type of help, or a pointer in the right direction; many thanks in advance.
The output you show looks like result of a UNION query so consider:
SELECT Invitation.InviteID AS ResultID, Invitation.Name, Invitation.Email, True AS InvitedUser
FROM Invitation
UNION
SELECT SalesAgent.SalesAgentID, User.Name, User.Email, False AS InvitedUser
FROM [User] INNER JOIN SalesAgent ON User.UserID = SalesAgent.UserID
WHERE (((User.Name) Not In (SELECT [Name] FROM [Invitation])));
For my further work I need to create a lookup table where all the different IDs my data has (because of different sources) are noted.
It has to look like this:
Lookup_Table:
| Name | ID_source1 | ID_source2 | ID_source3 |
-----------------------------------------------
| John | EMP_992 | AKK81239K | inv1000003 |
Note, that Name and ID_Source1 are coming from the same table. The other IDs are coming from different tables. They share the same name value, so e.g. source 2 looks like this:
Source2 Table:
| Name | ID |
--------------------
| John | AKK81239K |
What is the SQL code to accomplish this? Im using Access and it doesnt seem to work with this code for source 2:
INSERT INTO Lookup_Table ([ID_Source2])
SELECT [Source2].[ID]
FROM Lookup_Table LEFT JOIN [Source2]
ON [Lookup_Table].[Name] = [Source2].[Name]
It just adds the ID from Source2 in a new row:
| Name | ID_source1 | ID_source2 | ID_source3 |
-----------------------------------------------
| John | EMP_992 | | |
| | | AKK81239K | |
Hope you guys can help me.
You're looking for an UPDATE query, not an INSERT query.
An UPDATE query updates existing records. An INSERT query inserts new records into a table.
UPDATE Lookup_Table
INNER JOIN [Source2] ON [Lookup_Table].[Name] = [Source2].[Name]
SET [ID_Source2] = [Source2].[ID]
I have a database containing two tables Team and User.
Every team can have one or two users in it.
I wish to select an output of the table Team such that information of the both the users from the table User are included.
It'll be easier to understand once I define the table structures.
Table Team:
+-----------+-------------------+-------------------+-----------------+
| team_name | user_one | user_two | team_note |
+-----------+-------------------+-------------------+-----------------+
| Team one | skuhsa#jdds.dfd | kgihse#kdhf.dfj | one to twenty |
| Team two | dsjgknsz#djfd.fkg | | three to thirty |
+-----------+-------------------+-------------------+-----------------+
Table User:
+-------------------+-----------+-----------------+
| email | user_name | user_note |
+-------------------+-----------+-----------------+
| skuhsa#jdds.dfd | skuhsaone | gimme money |
| kgihse#kdhf.dfj | kgihse | drop it |
| dsjgknsz#djfd.fkg | dsjgknsz | just eat it |
+-------------------+-----------+-----------------+
The output I'm looking for goes like this.
+-----------+--------------------+-----------+------------------+-----------+-----------------+
| team_name | user_one | user_name | user_two | user_name | team_note |
+-----------+--------------------+-----------+------------------+-----------+-----------------+
| Team one | skuhsa#jdds.dfd | skuhsaone | kgihse#kdhf.dfj | kgihse | one to twenty |
+-----------+--------------------+-----------+------------------+-----------+-----------------+
| Team two | dsjgknsz#djfd.fkg | dsjgknsz | | | three to thirty |
+-----------+--------------------+-----------+------------------+-----------+-----------------+
I have a good feeling that it can be done easily, but right now I'm trying all sorts of JOINs and stuff and ending up with duplicate results or rows.
If there is any PostgreSQL specific ways to do it, it'd just fine with me.
SELECT * FROM Team LEFT JOIN User ON Team.user_one=User.email works, but how do I select only the columns I want? i.e., how will it differentiate b/w columns for the first and the second user?
A couple of left joins should do the trick:
SELECT team_name, user_one, u1.user_name, user_two, u2.user_name, team_note
FROM team t
LEFT JOIN user u1 ON t.user_one = u1.email
LEFT JOIN user u2 ON t.user_one = u2.email
The answer is actually quite simple, as the comment says simply use a LEFT join, this could by saying LEFT JOIN [TableName]
SELECT * FROM [Team]
LEFT JOIN [User]
Also take a look at
http://www.w3schools.com/sql/sql_join_left.asp
Edit:
Your second option would be to do this:
SELECT * FROM [Team]
UNION
SELECT * FROM [User]
An inner join or a left join can be used to extract data from both tables.
But the result of the query will be more similar to the following:
+-----------+--------------------+-----------+-----------------+
| team_name | user_one | user_name | team_note |
+-----------+--------------------+-----------+-----------------+
| Team one | skuhsa#jdds.dfd | skuhsa | one to twenty |
+-----------+--------------------+-----------+-----------------+
| Team one | skuhsa#jdds.dfd | kgihse | one to twenty |
+-----------+--------------------+-----------+-----------------+
| Team two | dsjgknsz#djfd.fkg | dsjgknsz | three to thirty |
+-----------+--------------------+-----------+-----------------+
This is the best solution because you don't know how many users are present in a team what happens if they are 3 (or 100?) ? But it is different from your expectations so check if you agree with that form.
firstly you sould re-think aout tables. What is the meaning wirting user e-mails in two different tables? In the end you will get all of them in one table.
Other than that you shoul look at foreign key. Foreign keys link tables together. I think your tables must be like.
+-----------+-------------------+-------------------+-
| team_name | team_note | team_id(Primary key)
+-----------+-------------------+-------------------+
| Team one | one to twenty | 1
| Team two | stuff | 2
+-----------+-------------------+-------------------+
+-------------------+-----------+-----------------+-------------------------------------------------
| email | user_name | user_note | f_team_id(foreign_key) to team.team_id
+-------------------+-----------+-----------------+--------------------------------------
| skuhsa#jdds.dfd | skuhsaone | gimme money | 1
| kgihse#kdhf.dfj | kgihse | drop it | 1
| dsjgknsz#djfd.fkg | dsjgknsz | just eat it | 2
+-------------------+-----------+-----------------+------------------------------------------
After that
SELECT * FROM team JOIN user ON user.f_team_id=team.team_id; OR
SELECT * FROM team, user WHERE user.f_team_id=team.team_id;