Updating specific columns within the table of unsequential/skipping Id's - sql

I have a table with ~4k rows that need their data only in specific columns.
In other words UPDATE of only the specific columns within all the rows while in the same time not touching the data of existing columns - with nonsequential Id's e.g. (1,2,3,4,7,8,9,11 etc.).
So this query that I've written fails:
UPDATE dbo.SURFACE2
SET Xwgs = dt.Xwgs, Ywgs = dt.Ywgs
FROM
(
SELECT
Id as InId,
Xwgs,
Ywgs
FROM dbo.SURFACE2
WHERE
Id BETWEEN 3693 AND 7369
) dt
WHERE
Id = dt.InId - 3692
Since Id's are nonsequential not all the rows are filled and many are filled erroneously(in an expected destination row I have data for the earlier one source row).
What would be a better way of accomplishing this without having to recreate this into a new table with sorted Id's?

Your query is fine, but it can be simplified to:
UPDATE s
SET Xwgs = dt.Xwgs,
Ywgs = dt.Ywgs
FROM dbo.SURFACE2 s JOIN
dbo.SURFACE2 ss
ON s.Id = ss.InId - 3692
WHERE ss.Id BETWEEN 3693 AND 7369;

If I follow you correctly, you can use row_number() to renumber the rows first, then apply the logic:
with cte as (select s.*, row_number() over(order by id) rn from surface2)
update t
set t.Xwgs = s.Xwgs, t.Ywgs = s.Ywgs
from cte t
inner join cte s on s.rn = t.rn - 3692
where t.rn between 3693 and 7369

Query was straight; turns out I needed respective Id's for what I've imported from the
excel sheet.

Related

Get top 1 row for every ID

There is a few posts about it but i can't make it work...
I just want to select just one row per ID, something like row_number() over Partition in oracle but in access.
ty
SELECT a.*
FROM DATA as a
WHERE a.a_sku = (SELECT top 1 b.a_sku
FROM DATA as b
WHERE a.a_sku = b.a_sku)
but i get the same table Data out of it
Sample of table DATA
https://ibb.co/X4492fY
You should try below query -
SELECT a.*
FROM DATA as a
WHERE a.Active = (SELECT b.Active
FROM DATA as b
WHERE a.a_sku = b.a_sku
AND a.Active < b.Active)
If you don't care which record within each group of records with a matching a_sku values is returned, you can use the First or Last functions, e.g.:
select t.a_sku, first(t.field2), first(t.field3), ..., first(t.fieldN)
from data t
group by t.a_sku

SSRS Table of locations per item type

I have a basic query which shows what the latest product to be put in each location (FVTank) is:
SELECT TOP 1
T0.[DateTime],
T0.[TankName],
T1.[Item]
FROM
t005_pci_data T0
INNER JOIN t001_fvbatch T1 ON T1.[FVBatch] = T0.[FVBatch]
WHERE
T0.[TankName] = 'FV101'
UNION
SELECT TOP 1
T0.[DateTime],
T0.[TankName],
T1.[Item]
FROM
t005_pci_data T0
INNER JOIN t001_fvbatch T1 ON T1.[FVBatch] = T0.[FVBatch]
WHERE
T0.[TankName] = 'FV102'
[...etc...]
ORDER BY
T0.[DateTime] DESC
Which gives a result like this:
What I'd like to do is create a summary page on SSRS which would display all the locations which currently hold each item. Ideally it would look something like this:
There are 50 locations and 7 main items so I need it to have 8 headers (one additional one for "other".)
Is there a way to do this in SSRS? Or is there a better solution by doing it in SQL?
Thank you.
Add an additional column to your dataset that calculates a row number for each Item, ordered by the DateTime field:
row_number() over (partition by Item order by DateTime desc) as rn
Judging by your source query in your question, this may be best included as a wrapping select around your final query:
select DateTime
,TankName
,Item
,row_number() over (partition by Item order by DateTime desc) as rn
from(
<Your original query here>
) a
You can then use this as your row group, as without one you will not get the top aligned format you are after in each Item x column. Remember to delete the rn column but keep the grouping:
When you run this report you will get the following format (I didn't bother typing out all your data into my dataset query, hence the missing values):

Update only the top 1 row in sql server

I have a table as below:
As You see, the column officebudge updated with value for all individual offices. i want the update happen only top 1 office
like below:
any suggesion to update the top 1 record?
I used below code. but it updates all the office entries:
UPDATE budget
SET officebudge = ISNULL(ProjectedReturnCount,0)
FROM analyticsdata
join
(
select ofc.officeid,ofc.week,
max(ISNULL(ofc.ProjectedReturnCount,0)) ProjectedReturnCount
from
BudgetOffice ofc
INNER JOIN budget anal
on ofc.OfficeID = anal.OfficeID
and ofc.Week = anal.week
and ofc.RowStatus = 'a'
group by ofc.OfficeID,ofc.week
)z
on (z.officeid = budget.OfficeID
and z.Week = budget .week )
thanks for the help. I have attached a sql fiddle to demonstrate this.
http://sqlfiddle.com/#!3/a2b32/7
You can use CTE like this (I have used only few of your provided columns)
;With cte As
(Select *, Row_Number() Over(Partition By OfficeID order by RowID) As rn
From Employee)
update cte set OfficeBudge = 0 where rn>1
select * from Employee
Find the attached fiddle
sql fiddle demo
You can achieve that you want using cte (Common Table Expression)
https://msdn.microsoft.com/en-us/library/ms186734.aspx
Take a look at item B of the link above.

Selecting Random Record for each User returned in the results

I have seen several ways of selecting random records from a table using several methods. However, my need I am sure is here, I just cannot find it. I have a query using several tables. What my end goal is is to have one random record for each user returned.
In my result set, I get users and the work items they have. What I need is to only return one random work item per user. This is where I am getting stuck. ANy assistance would be greatly appreciated.
Here is my code. What I need is 1 random C.credentilaing_k per user.
select
U.FULLNAME as 'Chg_By',
CONVERT(DATE,AL.AUDITDATETIME) as 'DE_Date',
P.ID,
P.LONGNAME,
CONVERT(DATE,P.DATEOFBIRTH) as 'DOB',
C.CREDENTIALING_K,
C.entity_k,
R.DESCRIPTION as 'CVI_TYPE',
CG.GROUPDESCRIPTION,
C.APPLICATION_RECEIVED,
R1.DESCRIPTION as 'Cur_STATUS',
CONVERT(DATE,C.USERDEF_D3) as 'MSO_DUE_DT'
from
VisualCACTUS.AUDITLOG AL
JOIN VisualCACTUS.USERS U
on U.user_k = AL.USER_K
join VisualCACTUS.CREDENTIALING C
JOIN VisualCACTUS.PROVIDERS P
on P.provider_k = C.PROVIDER_K
JOIN visualcactus.CREDENTIALINGGROUP CG
on CG.CREDENTIALINGGROUP_K = C.CREDENTIALINGGROUP_K
JOIN VisualCACTUS.REFTABLE R
on R.reftable_k = C.TYPE_RTK
JOIN VisualCACTUS.REFTABLE R1
ON R1.REFTABLE_K = C.CREDENTIALINGSTATUS_RTK
on C.CREDENTIALING_K = AL.FILE_PRIMARYKEY
where
AUDITLOG_K in (select AUDITLOG_K from VisualCACTUS.AUDITLOG_RECORDLEVEL where TABLE_NAME = 'CREDENTIALING '
and
AUDITLOG_RECORDLEVEL_K in (SELECT AUDITLOG_RECORDLEVEL_K from VisualCACTUS.AUDITLOG_FIELDLEVEL where NEWVALUE_SHORT = 'D2LC0YSXXW'))
and
CONVERT(DATE, AUDITDATETIME) = DATEADD(day, -1, convert(date, GETDATE()))
I think you need something like this (in T-SQL):
SELECT *
FROM (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY NEWID()) rn
FROM yourTable) dt
WHERE
rn = 1;
What you want is to get a random record for a user if the user is having multiple records. We may do something as below (In Teradata):
select
*
from tablename
where
qualify row_number() (over partition by id order by column) = 1;
Here:
partition by - can have multiple columns seperated by comma incase you want to segregate your data based on few columns.
order by - can be given just to arrange the data in that segment based on your preference, it can be on date or anything as per your data.
=1 - signifies take the first among them.

Sql Server Query Selecting Top and grouping by

SpousesTable
SpouseID
SpousePreviousAddressesTable
PreviousAddressID, SpouseID, FromDate, AddressTypeID
What I have now is updating the most recent for the whole table and assigning the most recent regardless of SpouseID the AddressTypeID = 1
I want to assign the most recent SpousePreviousAddress.AddressTypeID = 1
for each unique SpouseID in the SpousePreviousAddresses table.
UPDATE spa
SET spa.AddressTypeID = 1
FROM SpousePreviousAddresses AS spa INNER JOIN Spouses ON spa.SpouseID = Spouses.SpouseID,
(SELECT TOP 1 SpousePreviousAddresses.* FROM SpousePreviousAddresses
INNER JOIN Spouses AS s ON SpousePreviousAddresses.SpouseID = s.SpouseID
WHERE SpousePreviousAddresses.CountryID = 181 ORDER BY SpousePreviousAddresses.FromDate DESC) as us
WHERE spa.PreviousAddressID = us.PreviousAddressID
I think I need a group by but my sql isn't all that hot. Thanks.
Update that is Working
I was wrong about having found a solution to this earlier. Below is the solution I am going with
WITH result AS
(
SELECT ROW_NUMBER() OVER (PARTITION BY SpouseID ORDER BY FromDate DESC) AS rowNumber, *
FROM SpousePreviousAddresses
WHERE CountryID = 181
)
UPDATE result
SET AddressTypeID = 1
FROM result WHERE rowNumber = 1
Presuming you are using SQLServer 2005 (based on the error message you got from the previous attempt) probably the most straightforward way to do this would be to use the ROW_NUMBER() Function couple with a Common Table Expression, I think this might do what you are looking for:
WITH result AS
(
SELECT
ROW_NUMBER() OVER (PARTITION BY SpouseID ORDER BY FromDate DESC) as rowNumber,
*
FROM
SpousePreviousAddresses
)
UPDATE SpousePreviousAddresses
SET
AddressTypeID = 2
FROM
SpousePreviousAddresses spa
INNER JOIN result r ON spa.SpouseId = r.SpouseId
WHERE r.rowNumber = 1
AND spa.PreviousAddressID = r.PreviousAddressID
AND spa.CountryID = 181
In SQLServer2005 the ROW_NUMBER() function is one of the most powerful around. It is very usefull in lots of situations. The time spent learning about it will be re-paid many times over.
The CTE is used to simplyfy the code abit, as it removes the need for a temporary table of some kind to store the itermediate result.
The resulting query should be fast and efficient. I know the select in the CTE uses *, which is a bit of overkill as we dont need all the columns, but it may help to show what is happening if anyone want to see what is happening inside the query.
Here's one way to do it:
UPDATE spa1
SET spa1.AddressTypeID = 1
FROM SpousePreviousAddresses AS spa1
LEFT OUTER JOIN SpousePreviousAddresses AS spa2
ON (spa1.SpouseID = spa2.SpouseID AND spa1.FromDate < spa2.FromDate)
WHERE spa1.CountryID = 181 AND spa2.SpouseID IS NULL;
In other words, update the row spa1 for which no other row spa2 exists with the same spouse and a greater (more recent) date.
There's exactly one row for each value of SpouseID that has the greatest date compared to all other rows (if any) with the same SpouseID.
There's no need to use a GROUP BY, because there's kind of an implicit grouping done by the join.
update: I think you misunderstand the purpose of the OUTER JOIN. If there is no row spa2 that matches all the join conditions, then all columns of spa2.* are returned as NULL. That's how outer joins work. So you can search for the cases where spa1 has no matching row spa2 by testing that spa2.SpouseID IS NULL.
UPDATE spa SET spa.AddressTypeID = 1
WHERE spa.SpouseID IN (
SELECT DISTINCT s1.SpouseID FROM Spa S1, SpousePreviousAddresses S2
WHERE s1.SpouseID = s2.SpouseID
AND s2.CountryID = 181
AND s1.PreviousAddressId = s2.PreviousAddressId
ORDER BY S2.FromDate DESC)
Just a guess.