I am trying to insert rows from one table to another that are not in the one I am moving them to. I also want to only move the ones that have the highest datestamp. (I want to only insert rows that are not in tb1 and have the max timestamp)
This is what I have so far:
INSERT INTO [db].[dbo].[tb1]
SELECT *
FROM tb2
WHERE ( dbo.tb2.STime = (SELECT Max(STime)
FROM dbo.tb2) )
AND ( EMPNO NOT IN (SELECT EMPNO
FROM [db].[dbo].[tb1]) );
I Get this error when I execute:
Msg 147, Level 15, State 1, Line 43 An aggregate may not appear in the
WHERE clause unless it is in a subquery contained in a HAVING clause
or a select list, and the column being aggregated is an outer
reference.
-EDIT
RESOLVED
WITH aggregateTime (maxTime) AS (
SELECT MAX(STime) AS maxTime
FROM tb2
)
INSERT INTO db.dbo.tb1
SELECT *
FROM tb2
INNER JOIN aggregateTime ON 1=1
WHERE tb2.STime = aggregateTime.maxTime AND EMPNO NOT IN (SELECT EMPNO FROM tb1);
You could use a CTE with just one column that is the maxtime from tb2. Then join on the CTE and reference it when checking for if its the max or not.
WITH aggregateTime (maxTime) AS (
SELECT MAX(STime) AS maxTime
FROM tb2
)
INSERT INTO tb1 (id, EMPNO, Street1)
SELECT id, EMPNO, Street1
FROM tb2
INNER JOIN aggregateTime ON 1=1
WHERE tb2.STime = aggregateTime.maxTime AND EMPNO NOT IN (SELECT EMPNO FROM tb1);
Working SQL Fiddle: http://sqlfiddle.com/#!6/141bf/4
Related
I am trying to write a SQL statement that first gets only the distinct values of column 1, I then want to compare this with the same table but remove any rows that have a value in column 2
For example, the value 10142 in FieldID when I write a select that doesn't include 10142 it only removes the 1 row but also the subsequent ID column to have no rows.
So in the screenshot, I should only see all results for only ID 634 as 633 has the FieldID value 10142.
I tried initially getting a distinct ID value into a temporary table and then filtering in another select where the FieldID was not equal to 10142 but still not seeing the correct result.
This is my query:
SELECT DISTINCT id
INTO #TEMP
FROM tbl_WorkItemCustomLatest
ORDER BY ID ASC
SELECT a.*
FROM #TEMP
INNER JOIN dbo.tbl_WorkItemCustomLatest AS A ON #TEMP.id = A.id
WHERE A.FieldID != 10142
ORDER BY A.ID ASC
Any help is much appreciated.
With NOT EXISTS:
select t.* from tbl_WorkItemCustomLatest t
where not exists (
select 1 from tbl_WorkItemCustomLatest
where id = t.id and FieldId = 10142
)
or with NOT IN:
select * from tbl_WorkItemCustomLatest
where id not in (select id from tbl_WorkItemCustomLatest where FieldId = 10142)
I need to update CTE o/p one of the column value (top 1 record) based on the latest timestamp & then return.
Query
WITH cte AS (
select
dt_zone.zone_name,
dt_material_status.mtstatus_name,
dt_historicalzone.visit_time_in
FROM ((public.dt_historicalzone
INNER JOIN dt_material_status
ON dt_historicalzone.mtstatus_id = dt_material_status.mtstatus_id)
INNER JOIN dt_zone ON dt_historicalzone.zone_id = dt_zone.zone_id)
WHERE material_id = 'ELS46885'
ORDER BY dt_historicalzone.zone_id DESC)
UPDATE cte SET cte.mtstatus_name = true WHERE SELECT * FROM cte LIMIT 1;
SELECT * FROM cte
You may try using an update join, with Postgres' syntax, including a CTE for the limit portion of the query:
WITH cte AS (
SELECT dh.mtstatus_id
FROM dt_historicalzone dh
INNER JOIN dt_zone dz
ON dh.zone_id = dz.zone_id
ORDER BY zone_id DESC
LIMIT 1
)
UPDATE dt_material_status d
SET mtstatus_name = true
FROM cte t
WHERE d.mtstatus_id = t.mtstatus_id AND
d.material_id = 'ELS46885';
when you update a CTE, the background table is getting updated. You can have only one statement below CTE. Post that CTE loses its scope. You can only go for UPDATE statement, post CTE. I have modified the CTE and updated the top 1 row.
The above statement is applicable for SQL Server. In Postgres, the CTE cannot be target of UPDATE statements. See the below error in Postgres.
Query Error: error: relation "cte" cannot be the target of a modifying
statement
WITH cte AS (
select top 1
dt_zone.zone_name,
dt_material_status.mtstatus_name,
dt_historicalzone.visit_time_in
FROM public.dt_historicalzone
INNER JOIN dt_material_status
ON dt_historicalzone.mtstatus_id = dt_material_status.mtstatus_id
INNER JOIN dt_zone ON dt_historicalzone.zone_id = dt_zone.zone_id
WHERE material_id = 'ELS46885'
ORDER BY dt_historicalzone.zone_id DESC)
UPDATE cte
SET mtstatus_name = true
I have tried with sample data for a CTE update. Below works fine in SQL Server.
create table #test(a int)
create table #test2(a int, b int)
insert into #test values (1)
insert into #test2 values (1,1)
;WITH CTE as
(
select top 1 t.a, t2.b
FROM #test as t
join #test2 as t2
on t.a = t2.a
order by t.a desc
)
update cte set b = 0
select * from #test2
I am putting together a query in SQL Server but having issues with the sub-query
I wish to use the max(loadid) and count the number of records the query returns.
So for example my last loadid is 400 and the amount of records with 400 is 2300, so I would my recor_count column should display 2300. I have tried various ways below but am getting errors.
select count (loadid)
from t1
where loadid = (select max(loadid) from t1) record_count;
(select top 1 LOADID, count(*)
from t1
group by loadid
order by count(*) desc) as Record_Count
Showing loadid and number of matching rows with the use of grouping, ordering by count and limiting the output to 1 row with top.
select top 1 loadid, count(*) as cnt
from t1
group by loadid
order by cnt desc
This may be easier to achieve with a window function in the inner query:
SELECT COUNT(*)
FROM (SELECT RANK() OVER (ORDER BY loadid DESC) AS rk
FROM t1) t
WHERE rk = 1
Another simplest way to achieve the result :
Set Nocount On;
Declare #Test Table
(
Id Int
)
Insert Into #Test(Id) Values
(397),(398),(399),(400)
Declare #Abc Table
(
Id Int
,Value Varchar(100)
)
INsert Into #Abc(Id,Value) Values
(398,'')
,(400,'')
,(397,'')
,(400,'')
,(400,'')
Select a.Id
,Count(a.Value) As RecordCount
From #Abc As a
Join
(
Select Max(t.Id) As Id
From #Test As t
) As v On a.Id = v.Id
Group By a.Id
I have 2 tables and want to compare them and modify tableA (set NameMod = 1) if it has different rows.
To compare tables I use:
select Id, Name from tableB
except
select Id, Name from tableA
And then I want to modify tableA:
update tableA Set NameMod = 1
where exists (
select Id, Name from tableB
except
select Id, Name from tableA
)
But I can only use EXISTS before the sub-query and in this case it updates all elements in table not different rows.
Could you try this:
MERGE TableA AS [Target]
USING TableB AS [Source]
ON [Target].[ID] = [Source].[ID]
AND [Target].[Name ] = [Source].[Name]
WHEN NOT MATCHED BY TARGET
THEN UPDATE SET NameMod = 1;
It is using the MERGE clause.
If you do not like the clause, you can use CTE like this:
;WITH IdsForUpdate ([id]) AS
(
SELECT DISTINCT Id
FROM
(
select Id, Name from tableB
except
select Id, Name from tableA
) DS([id], [name])
)
update tableA
Set NameMod = 1
FROM tableA A
INNER JOIN IdsForUpdate B
ON A.[id] = B.[id];
I've some records in table_3 and I want to insert that record to table_2 but value of first column (Id) will be (NUMBER+1) of table_1. My code is
INSERT INTO TABLE_2(Id,NAME)
SELECT (SELECT MAX(NUMBER) FROM TABLE_1)+1 AS Id,name
FROM TABLE_3
Count of table_1 is 200. and count of TABLE_3 is 10. I want new inserted Ids are like
(201,202,203,204,205,206,207,208,209,210)
but from query am getting is like...
(201,201,201,201,201,201,201,201,201,201)
you can do it simply with only one select using ROW_NUMBER() and a group by
INSERT INTO TABLE_2(Id,NAME)
SELECT MAX(NUMBER) + ROW_NUMBER() OVER (ORDER BY name),name
FROM TABLE_3
group by name
In your query (SELECT MAX(NUMBER) FROM TABLE_1)+1 is always the same, since MAX(NUMBER) is just 200.
If you want to increment by 1 for each new record inserted, starting at (SELECT MAX(NUMBER) FROM TABLE_1)+1, try this:
INSERT INTO TABLE_2 (Id, NAME)
SELECT Id + rn, name
FROM (
SELECT (SELECT MAX(NUMBER) FROM TABLE_1) AS Id, name,
ROW_NUMBER() OVER (ORDER BY name) AS rn
FROM TABLE_3 ) t