TSQL: INSERT or UPDATE from SELECT result - sql-server

I have the following query where I grab some data from tables, and use the result to insert into a table called finalTable. finalTable.col1 is a pk. However, there are some rows in the finalTable that already exists with the same pk prior to running the below query. I want to change it so that it inserts(if the pk does not exist in finalTable) or updates(if the pk already exist in finalTable).
INSERT INTO finalTable (col1, col2, col3, col4, col5)
(
SELECT o.id, 14, 0, 1, 4
FROM Table1 c
INNER JOIN Table2 m ON c.ID = m.ID
INNER JOIN Table3 o ON m.ID = o.ID
WHERE c.ID = 40
)
One solution I came up with is deleting any relevant rows in finalTable prior to running the above query.
Another solution I came up with is to use "if exists". I would put the select query in the if exists statement, the clause of the if, and the clause of the else. I don't like this solution as I have to put the select query in 3 places, rather than in just 1 place.
if exists(...)
begin
... -- update
end
else
begin
... -- insert
end

You can use MERGE statement for such cases.
MERGE finaltable as target
USING (SELECT o.id
FROM Table1 c
INNER JOIN Table2 m ON c.ID = m.ID
INNER JOIN Table3 o ON m.ID = o.ID
WHERE c.ID = 40) as source
ON target.col1=source.id
WHEN MATCHED THEN
UPDATE SET col2=14,col3=0,col4=1,col5=4
WHEN NOT MATCHED THEN
INSERT (col1, col2, col3, col4, col5)
VALUES (source.id,14, 0, 1, 4)

Related

Applying outer layer that wrapping two select statement

I have two query which has successfully inner join
select t1.countResult, t2.sumResult from (
select
count(column) as countResult
from tableA join tableB
on tableA.id = tableB.id
group by name
)t1 inner join (
select
sum(column) as sumResult
from tableA
join tableB
on tableA.id = tableB.id
group by name
)t2
on t1.name= t2.name
The above query will return me the name and the corresponding number of count and the sum. I need to do a comparison between the count and sum. If the count doesnt match the sum, it will return 0, else 1. And so my idea was implementing another outer layer to wrap them up and use CASE WHEN. However, I've failed to apply an outer layer just to wrap them up? This is what I've tried:
select * from(
select t1.countResult, t2.sumResult from (
select
count(column) as countResult
from tableA join tableB
on tableA.id = tableB.id
group by name
)t1 inner join (
select
sum(column) as sumResult
from tableA
join tableB
on tableA.id = tableB.id
group by name
)t2
on t1.name= t2.name
)
Alright the problem can be solved by simply assigning a name to the outer layer.
select * from(
select t1.countResult, t2.sumResult from (
select
count(column) as countResult
from tableA join tableB
on tableA.id = tableB.id
group by name
)t1 inner join (
select
sum(column) as sumResult
from tableA
join tableB
on tableA.id = tableB.id
group by name
)t2
on t1.name= t2.name
) as whatever //SQL Server need a name to wrap
Hope it will help any newbie like me
Ok, so far you have selected everything your first select has generated (kinda useless, but a start for what you want ;) )
SELECT CASE
WHEN countresult=sumresult THEN 'Equal'
ELSE 'Not'
END
FROM ( --your join select --
)
I don't have any sample data to test this so can just go on your code.
Your queries for t1 & t2 look identical - why don't you just do a sum & count in 1 step?
SELECT COUNT(column) AS countResult
,SUM(column) AS sumResult
FROM tableA INNER JOIN tableB
ON tableA.id = tableB.id
GROUP BY name
Also, as you mention you are a newb - read up on Common Table Expressions in SQL Server.
Before SQL 2005 you had to write these convoluted queries within queries within...
Get into the habit of using CTEs now.

SQL Server SELECT statement

I need a query that returns rows from table A if value X in table A is not the same as the sum of value Y from corresponding row(s) in table B. The issue is that there may or may not be rows in table B that correspond to the rows in table A, but if there no rows in table B, then the rows from table A should still be returned (because there is not a matching value in table B.) So it is like a LEFT OUTER join scenario, but the extra complication of having a comparison as an additional selection criteria.
I have a query that does the opposite, ie. returns rows if the value in table A is the same as the value of row(s) in table B, but sadly this isn't what I need!
SELECT TableA.id, TableA.bdate
FROM TableA
LEFT JOIN TableB ON TableB.ID = TableA.id
WHERE TableA.select_field = 408214
AND TableA.planned_volume =
(select sum(actual_volume)
from
TableB
where TableB.id = TableA.id)
ORDER BY TableA.id
Any help greatly appreciated.
How about something like this:
SELECT TableA.Id, TableA.bdate
FROM TableA
LEFT JOIN
(
SELECT Id, SUM(actual_volume) AS b_volume
FROM TableB
GROUP BY Id
) AS TableBGrouping
ON TableBGrouping.Id= TableA.Id AND TableA.planned_volume <> b_volume
ORDER BY TableA.Id
WITH TotalVolumes
AS
(
SELECT id, SUM(actual_volume) AS total_volume
FROM TableB
GROUP
BY id
)
SELECT id, bdate, planned_volume
FROM TableA
EXCEPT
SELECT A.id, A.bdate, T.total_volume
FROM TableA AS A
JOIN TotalVolumes AS T
ON A.id = T.id;
SELECT TableA.id, TableA.bdate
FROM TableA
LEFT JOIN TableB ON TableB.ID = TableA.id
AND TableA.planned_volume <>
(select sum(actual_volume)
from
TableB
where TableB.id = TableA.id)
ORDER BY TableA.id

Using where condition in sql query

I have an sql query like this
Select col1, (select abc from table2 where def=1) as col2
From Table1 inner join table3 on Table1.id = table3.id
Where col2 = 4
The problem is that the where condition doesn't work. I get an error saying
Invalid column name 'col2'
Kindly help me fix this sql query.
Thanks in advance
You can define it in a CROSS APPLY and then reference in the SELECT and WHERE
SELECT col1,
col2
FROM Table1
INNER JOIN table3
ON Table1.id = table3.id
CROSS APPLY (SELECT abc
FROM table2
WHERE def = 1) C(col2)
WHERE col2 = 4
Using a CTE (Common Table Expression):
WITH SubQuery AS (Col2) {
SELECT
ABC
FROM
table2
WHERE
def = 1
}
SELECT
T.Col1,
S.Col2
FROM
SubQuery S,
Table1 T
INNER JOIN table3 t3
ON T.id = t3.id
WHERE
S.Col2 = 4
Although I must say I agree with the first comment - this makes no sense since your subquery is not correlated (joined) to the rest of your query...

SQL server 2000 insert rows when join does not match

I would simply like to insert rows from a table to another if rows does not exist in the target.
How should I code that? with inner join?
Below is the query which returns rows that match between source and target
select * from LOG_S1201_REFERENCE_T1 b
inner join LOG_S1201_REFERENCE_STAGING_WT5 a on b.OU_ID=a.OU_ID and
b.Plant_desc=a.Plant_desc and b.workshop=a.workshop and
b.SerieNum=a.SerieNum and b.Operation_type=a.Operation_type and
b.PC10DBName=a.PC10DBName and b.SimuDBName=a.SimuDBName and
b.ProgramName=a.ProgramName and b.Calibre=a.Calibre
Copying rows can be done through INSERT SELECT
Need an example?
INSERT INTO new_table (col1, col2, col3)
SELECT col4, col5, col6
FROM old_table
HAVING !(SELECT COUNT(*) FROM new_table WHERE col1 = old_table.col4)
Join the table that has all rows with left join with the table that has some of the rows.
Filter one of the left joined table column with IS NULL
INSERT INTO your_table
select b.*
from LOG_S1201_REFERENCE_T1 b
left join LOG_S1201_REFERENCE_STAGING_WT5 a on b.OU_ID=a.OU_ID and b.Plant_desc=a.Plant_desc and b.workshop=a.workshop and b.SerieNum=a.SerieNum and b.Operation_type=a.Operation_type and b.PC10DBName=a.PC10DBName and b.SimuDBName=a.SimuDBName and b.ProgramName=a.ProgramName and b.Calibre=a.Calibre
WHERE a.OU_ID IS NULL
In order to select rows that do NOT match you need to do a left join.
INSERT INTO LOG_S1201_REFERENCE_T1 b2
SELECT a.* FROM LOG_S1201_REFERENCE_STAGING_WT5 a
LEFT JOIN LOG_S1201_REFERENCE_T1 b ON
(b.OU_ID=a.OU_ID
AND b.Plant_desc=a.Plant_desc
AND b.workshop=a.workshop
AND b.SerieNum=a.SerieNum
AND b.Operation_type=a.Operation_type
AND b.PC10DBName=a.PC10DBName
AND b.SimuDBName=a.SimuDBName
AND b.ProgramName=a.ProgramName
AND b.Calibre=a.Calibre)
WHERE b.OU_ID IS NULL
This will select all rows from a that are not in b which will then be inserted into a.
Afterwards a and b should be identical (except for b rows that are not in a).

Sql server DELETE and WITH clause

I need to build an SQL statement to delete from certain table the records that match another select statement.
In Teradata we use
delete from table1
where (col1, col2) in (
select col1,col2
from table2
)
While in SQL Server it's not allowed to have more than 1 column in the WHERE..IN clause. I thought I can use the WITH clause:
with tempTable(col1,col2) as (
select col1,col2
from table2
)
delete from table1
where table1.col1 = tempTable.col1
and table1.col2 = tempTable.col2
How to use WITH..DELETE clause? Is there another way?
This should do it:
DELETE Table1
from Table1 t1
inner join tempTable t2
on t2.Col1 = t1.Col1
and t2.Col2 = t1.Col2
First build a query that selects the rows you need:
SELECT t1.*
FROM [Table1] t1
INNER JOIN [Table2] t2 ON t1.[col1] = t2.[col1] AND t1.[Col2]=t2.[Col2]
Test it to make sure it returns exactly the rows you want to delete. Then turn it into a delete statement by changing the "SELECT" to "DELETE" and removing the column list:
DELETE t1
FROM [Table1] t1
INNER JOIN [Table2] t2 ON t1.[col1] = t2.[col1] AND t1.[Col
delete from table1 t1 where exists
(
select 1 from table2 t2 where t1.col1 = t2.col1 and t1.col2 > t2.col2
)
with tempTable(col1,col2) as (
select col1,col2
from table2
)
delete table1 from tempTable
where table1.col1 = tempTable.col1
and table1.col2 = tempTable.col2
This works for me
WITH CTE AS
(
SELECT TOP 50000 *
from v020101hist order by data
)
DELETE FROM CTE

Resources