Update a single table based on data from multiple tables SQL Server 2005,2008 - sql

I need to update table one using data from table two. Table one and two are not related by any common column(s). Table three is related to table two.
Ex : table one(reg_det table)
reg_det_id | reg_id | results
101 | 11 | 344
table two :(temp table)
venue | results
Anheim convention center | 355
Table three (regmaster-tbl)
reg_id| venue
11 | Anaheim convention center
I need to update results column in table one using data from table two. But table one and two are not related. Table two and three and table one and three are related as you can see above. Can anyone please suggest any ideas! I need the results value to be 355 in table one and this data is coming from table 2, but these two are unrelated, and they can be related using table three. Sorry if it is confusing!

Fairly straight forward:
UPDATE T1
SET result = t2.results
FROM [table one] T1
INNER JOIN [table three] t3
on t1.reg_id = t3.reg_id
INNER JOIN [table two] T2
on t2.venue = t3.venue

Almost a question instead of an answer. :)
Couldn't you use an implied inner join?
UPDATE rd
SET rd.results = tt.results
FROM reg_det rd, regmaster rm, temptable tt
WHERE rm.reg_id = rd.reg_id
AND rm.venue = tt.venue;
I find it easier to read, and this syntax works in a SELECT statement, with the same meaning as an explicit inner join.

Try this:
UPDATE rd
SET rd.results = t.results
FROM reg_det rd
JOIN regmaster rm ON rm.reg_id = rd.reg_id
JOIN temptable t ON t.venue = rm.venue
WHERE t.results = 355
I added a WHERE clause because otherwise it will update all reg_det records that have matches in regmaster and temptable.

Related

SQL query to override content of column when matched column

Please who can help with this scenario?
I have two tables, both they have a common column ID, and Table 1 has a column Title. Normally I should update the content of this Title column for some ID, but since the table was already in use somewhere else, it wasn't a good idea to change data directly in Table 1.
That's why I created a new table table 2, which hold only the Title that must be changed associated with these ID that must be changed.
Now I am trying to get these updated titles from table 2, when there is a matching ID in table 1, otherwise show only the contents of table 1.
The result should be something like that but without using If statements.
__ID__ Title
| | | |
| | | |
You can use LEFT OUTER JOIN to this new table and COALESCE() function to say "If there is data in the new table, use it, otherwise use the data in the existing table" . Something like:
SELECT t1.id, COALESCE(t2.title, t1.title) as title
FROM t1
LEFT OUTER JOIN t2 ON t1.id = t2.id;

SQL - include results you are looking for in a column and set all other values to null

I have two tables, one with orders and another with order comments. I want to join these two tables. They are joined on a column "EID" which exists in both tables. I want all orders. I also want to see all comments with only certain criteria AND all other comments should be set to null. How do I go about this?
Orders Table
Order_Number
1
2
3
4
Comments Table
Comments
Cancelled On
Ordered On
Cancelled On
Cancelled On
In this example I would like to see for my results:
Order_Number | Comments
1 | Cancelled On
2 | Null
3 | Cancelled On
4 | Cancelled On
Thanks!
This seems like a rather trivial left join.
select o.order_number, c.comments
from orders o
left join comments c
on o.eid = c.eid
and (here goes your criteria for comments)
Tested on Oracle, there might be subtle syntax differences for other DB engines.
It depends on one condition:
Are you trying to SET the other comments to null? (replace the values in the table)
or
Are you trying to DISPLAY the other comments as null? (dont display them)
If you want to change the values in the table use
UPDATE `table` SET `column` = null WHERE condition;
otherwise use:
SELECT column FROM table JOIN othertable WHERE condition;

Stored procedure performance issue when grabbing data from many secondary tables

Let me explain the scenario of my stored procedure: I have to populate a table for which columns are coming from several tables. Below is one example table out of the several tables that I am using in my query
Data
PrimaryID1 PrimaryID2 KeyID Data
--------------------------------------------------------------
001 0011 1 abc1
001 0011 2 abc2
002 0021 1 xyz1
Since the granualar data is in 'PrimaryID1' and 'PrimaryID2' I am using correlated query based on the 'KeyID' to differentiate different fields in my destination table that I am populating. I am also dealing with huge amount of data in each of the 7 to 8 tables of data. Initially I had all the correlated queries in one single SQL statement, but that didn't work out (obviously!!). Then I separated each set of table into separate CTE part and then tried to insert into the final query, later I came to know CTEs absolutely do nothing about query performance, so I jumped to temp tables, populated each set of data into separate temp tables created non-clustered indexes in each of the fields that I am using in the table and finally tried to join it in the final query, but still this too didn't work out.
Let me explain the query that I have written here. I am taking data from two tables one happens to be PrimaryTable and another happens to be Secondary table. The granular data for PrimaryTable is in PrimaryID1 and PrimaryID2 but in SecondaryTable the granularity further goes down to KeyID and its respective data column Data. So there are 8 secondary tables that I am dealing with each different to one another, hence I end with queries for each secondary tables with a host of columns for it. This is how the query that I have developed looks like. In total I have around 280 odd columns in my query coming from 8 different secondary tables.
Query:
SELECT
PP.PrimaryID1,
PP.PrimaryID2,
(SELECT PPA.Data1
FROM SecondaryTable1 PPA
WHERE PPA.PrimaryID1 = PP.PrimaryID1 AND
PPA.PrimaryID2 = PP.PrimaryID2 AND PPA.KeyID = 1) AS DataField1,
(SELECT PPA.Data2
FROM SecondaryTable1 PPA
WHERE PPA.PrimaryID1 = PP.PrimaryID1 AND
PPA.PrimaryID2 = PP.PrimaryID2 AND PPA.KeyID = 2) AS DataField2,
(SELECT PPA.Data3
FROM SecondaryTable1 PPA
WHERE PPA.PrimaryID1 = PP.PrimaryID1 AND
PPA.PrimaryID2 = PP.PrimaryID2 AND PPA.KeyID = 3) AS DataField3
FROM
PrimaryTable PP
I am dealing with 8 such secondary tables with the count of records ranging from 28 million to 100 thousand. I hope this was helpful.
For your sample, you should be able to use a simple JOIN. Joins are generally more efficient than nested subqueries (although, knowing nothing about your indexing, it's hard to tell for sure if it solves your performance problem)
SELECT
PP.PrimaryID1,
PP.PrimaryID2,
PPA1.Data1 AS DataField1,
PPA2.Data2 AS DataField2,
PPA3.Data3 AS DataField3
FROM PrimaryTable PP
JOIN SecondaryTable1 PPA1
ON PPA1.PrimaryID1 = PP.PrimaryID1 AND PPA1.PrimaryID2 = PP.PrimaryID2
AND PPA1.KeyID = 1
JOIN SecondaryTable1 PPA2
ON PPA2.PrimaryID1 = PP.PrimaryID1 AND PPA2.PrimaryID2 = PP.PrimaryID2
AND PPA2.KeyID = 2
JOIN SecondaryTable1 PPA3
ON PPA3.PrimaryID1 = PP.PrimaryID1 AND PPA3.PrimaryID2 = PP.PrimaryID2
AND PPA3.KeyID = 3

Join on two dis-similar column

I need to join one column of a table to a column of another table.
Now these two column consists the geographic region data. But the issue is the column dont have exactly same strings od data.
For ex. Latin America in one column and LATM in another.
The data is table if had been same string would be the simplest joins but these two mean the same but then are different strings . What do I use to accomplish my task.
I need to do is
Select * from Table1 Inner Join Table2 on table1.region = table2.region
You would need to create a mapping table which maps every possible region in Table1.region to every possible region in Table2
for example your Mapping table be like.
MappingTable
--------------------------
Region1 | Region 2
--------------------------
Latin America | LATM
Europe | EUR
.....
The you can create a join like
Select *
from
Table1
inner join
MappingTable
on
Table1.region = MappingTable.Region1
inner join
Table2
on
MappingTable.Region2 = Table2.region
You need to make another table which contains information of TWO table Joining like 'Latin America' = 'LATM' and then have to use this table in join.

How to build virtual columns?

Sorry if this is a basic question. I'm fairly new to SQL, so I guess I'm just missing the name of the concept to search for.
Quick overview.
First table (items):
ID | name
-------------
1 | abc
2 | def
3 | ghi
4 | jkl
Second table (pairs):
ID | FirstMember | SecondMember Virtual column (pair name)
-------------------------------------
1 | 2 | 3 defghi
2 | 1 | 4 abcjkl
I'm trying to build the virtual column shown in the second table
It could be built at the time any entry is made in the second table, but if done that way, the data in that column would get wrong any time one of the items in the first table is renamed.
I also understand that I can build that column any time I need it (in either plain requests or stored procedures), but that would lead to code duplication, since the second table can be involved in multiple different requests.
So is there a way to define a "virtual" column, that could be accessed as a normal column, but whose content is built dynamically?
Thanks.
Edit: this is on MsSql 2008, but an engine-agnostic solution would be preferred.
Edit: the example above was oversimplified in multiple ways - the major one being that the virtual column content isn't a straight concatenation of both names, but something more complex, depending on the content of columns I didn't described. Still, you've provided multiple paths that seems promising - I'll be back. Thanks.
You need to join the items table twice:
select p.id,
p.firstMember,
p.secondMember,
i1.name||i2.name as pair_name
from pairs as p
join items as i1 on p.FirstMember = i1.id
join items as i2 on p.SecondMember = i2.id;
Then put this into a view and you have your "virtual column". You would simply query the view instead of the actual pairs table wherever you need the pair_name column.
Note that the above uses inner joins, if your "FirstMember" and "SecondMember" columns might be null, you probably want to use an outer join instead.
You can use a view, which creates a table-like object from a query result, such as the one with a_horse_with_no_name provided.
CREATE VIEW pair_names AS
SELECT p.id,
p.firstMember,
p.secondMember,
CONCAT(i1.name, i2.name) AS pair_name
FROM pairs AS p
JOIN items AS i1 ON p.FirstMember = i1.id
JOIN items AS i2 ON p.SecondMember = i2.id;
Then to query the results just do:
SELECT id, pair_name FROM pair_names;
You could create a view for your 'virtual column', if you wanted to, like so:
CREATE VIEW aView AS
SELECT
p.ID,
p.FirstMember,
p.SecondMember,
a.name + b.name as 'PairName'
FROM
pairs p
LEFT JOIN
items a
ON
p.FirstMember = a.ID
LEFT JOIN
items b
ON
p.SecondMember = b.ID
Edit:
Or, of course, you could just use a similar select statement every time.
When selecting from tables you can name the results of a column using AS.
SELECT st.ID, st.FirstMember, st.SecondMember, ft1.Name + ft2.Name AS PairName
FROM Second_Table st
JOIN First_Table ft1 ON st.FirstMember = ft1.ID
JOIN First_Table ft2 ON st.SecondMember = ft2.ID
Should give you something like what you are after.