Update first rows that match condition - sql-server

Update table1
set column1 = 'abc', column2 = 25
where column3 IN ('John','Kate','Tim')
Column3 contains John twice (two associated rows/records), similarly - it has Kate third times and Tim twice.
How can I adjust the query so that the update affects only the first row with John, the first row with Kate and the first with Tim?
For the reference, here is table1:
column1 column2 column3
aa 2 John (!)
affd 24 John
dfd 5 Tim (!)
ss 77 Kate (!)
s 4 Tim
s 1 Kate
sds 34 Kate
I want to update only the rows marked with (!)
I am especially interested in Ms Access! - but also curious how this is done in Sql Server in case it differs. Thank you!

Sql Server solution - Note, you must have a unique identity column for this to work (or some set of unique columns).
UPDATE table1
SET column1 = 'abc',
column2 = 25
WHERE id IN (SELECT id
FROM (SELECT id,
Row_number()
OVER (
ORDER BY rowyouwanttoorderby ) AS ROWNUM
FROM table1
WHERE column3 IN ( 'John', 'Kate', 'Tim' )) AS temp
WHERE rownum = 1)

Related

MS SQL split values in same table

Good day
I have :
TableX
Column1
John Smith 007
Tera Name 111
Bob Eva 554
I need
TableX
Column1 Column2
John Smith 007 007
Tera Name 111 111
Bob Eva 554 554
I created code but not work. I think there must be join to recognise columns.
ALTER TABLE [dbo].[TableX]
ADD Column2 varchar (50);
UPDATE [dbo].[TableX] SET
Column1=Column2
WHERE select SUBSTRING([Column1], PATINDEX('%[0-9]%', [Column1]
), LEN([column1]))
Thanks for help
If the number you want to extract is always at the end, then you can use:
PATINDEX('%[^0-9]%', REVERSE(Column1))
to get the index of the first character that is not a number, starting from the end.
So, to extract the number you can use:
RIGHT(Column1, PATINDEX('%[^0-9]%', REVERSE(Column1)) - 1)
Hence, the UPDATE will look like this:
UPDATE [dbo].[TableX]
SET Column2 = RIGHT(Column1, PATINDEX('%[^0-9]%', REVERSE(Column1)) - 1)
Demo here
Assuming required part length = 3
UPDATE [dbo].[TableX] SET
column2 = RTRIM(right(column1, CHARINDEX('/', column1) +3))

Adding values from a different table based on values in multiple columns of another table

I have 2 Tables
Table 1
Name column2 column3 column 4
Suzy English null null
Rocky Polish Irish null
John English American Funny
George Funny English null
Table 2
Column Value
English 2
Polish 3
Irish 2
Funny 0
American 1
The values in Column in Table 2 are unique.
I want to add a column in Table 1 which finds all the matching values from columns 2, 3 and 4 in table 1, finds the corresponding values in the ‘column’ in table 2 and the adds the corresponding values, So that Table 1 now is updated to look like
Table 1
Name column2 column3 column 4 Total
Suzy english null null 2
Rocky Polish Irish null 5
John English American Funny 3
George Funny English null 2
Is this possible at all? Or do I need to have another query first?
Your table structures are less than ideal, since apparently all of column2, column3 and column4 in table 1 contain items of the same "type".
There are various ways of creating your totals - we can either perform multiple joins or use a correlated subquery. I'm using the subquery here:
select
*,
(select SUM(t2.Value) from Table2 t2
where t2.Column1 in (t1.Column2,t1.Column3,t1.Column4)) as TotalValue
from
Table1 t1
You can use left join and do addition as below
select t1.*, [Total] = isnull(C2.Value,0) + isnull(C3.Value,0) + isnull(C4.Value,0)
from [Table 1] t1
left join [Table 2] c2 on t1.Column1 = c2.[Column]
left join [Table 2] c3 on t1.Column1 = c3.[Column]
left join [Table 2] c4 on t1.Column1 = c4.[Column]

deleting duplicates based on value of another column

I have a table with 3 columns and the first column is 'name'. Some names are entered twice, some 3 times and some more than that. I would like to keep only one value for each name and delete the extra rows based on the values of Column 2 and 3. If column 2 and 3 are null, I would like to delete that row.
There are no primary keys or id column.
There are about 2.75 million rows in the table.
Would like to delete using one query(preferably) in SQL 14. Can someone help please?
Name column2 column3
Suzy english null
Suzy null null
Suzy null 5
John null null
John 7 7
George null benson
George null null
George benson null
George 5 benson
Would like to have it as:
Name column2 column3
Suzy english null
Suzy null 5
John 7 7
George benson null
George 5 benson
Many thanks in advance.
Use partitions over name with the appropriate order by:
WITH cte as (
SELECT ROW_NUMBER()
OVER (PARTITION BY name
ORDER BY case
when column1 = 'null' and column2 = 'null' then 3
when column2 = 'null' then 2
when column1 = 'null' then 1
else 0 end
) num
FROM mytable
)
delete from cte where num > 1
This deletes duplicates, keeping in order of preference, rows with:
both column1 and column2 not null (random one kept if there are multiple of these)
column1 not null
column2 not null
both column1 and column2 null
Note that is query assumes (based on comments to question) that your "null" values are actually the text string "null" and not an SQL null.
If they were actually nulls, replace = 'null' with IS NULL.
Delete from yourtable
where column2 is null and column3 is null
above query is Based on this..
I would like to keep only one value for each name and delete the extra rows based on the values of Column 2 and 3. If column 2 and 3 are null, I would like to delete that row

delete multiple rows with same value in sql 14

I have a table with 3 columns and the first column is 'name'. Some names are entered twice, some 3 times and some more than that. I would like to keep only one value for each name and delete the extra rows.
There are no primary keys or id column.
There are about 1 million rows in the table.
Would like to delete using one query(preferably) in SQL 14. Can someone help please?
Name column2 column3
Suzy
Suzy
Suzy
John
John
George
George
George
George
Would like to have it as:
Name column2 column3
Suzy
John
George
Many thanks in advance
You can use row_number function, try like this,
WITH CTE
AS (
SELECT NAME
,column2
,column3
,RN = ROW_NUMBER() OVER (
PARTITION BY NAME ORDER BY NAME
)
FROM < YourTableName >
)
DELETE
FROM CTE
WHERE RN > 1

SQL Server - Transpose rows into columns

I've searched high and low for an answer to this so apologies if it's already answered!
I have the following result from a query in SQL 2005:
ID
1234
1235
1236
1267
1278
What I want is
column1|column2|column3|column4|column5
---------------------------------------
1234 |1235 |1236 |1267 |1278
I can't quite get my head around the pivot operator but this looks like it's going to be involved. I can work with there being only 5 rows for now but a bonus would be for it to be dynamic, i.e. can scale to x rows.
EDIT:
What I'm ultimately after is assigning the values of each resulting column to variables, e.g.
DECLARE #id1 int, #id2 int, #id3 int, #id4 int, #id5 int
SELECT #id1 = column1, #id2 = column2, #id3 = column3, #id4 = column4,
#id5 = column5 FROM [transposed_table]
You also need a value field in your query for each id to aggregate on. Then you can do something like this
select [1234], [1235]
from
(
-- replace code below with your query, e.g. select id, value from table
select
id = 1234,
value = 1
union
select
id = 1235,
value = 2
) a
pivot
(
avg(value) for id in ([1234], [1235])
) as pvt
I think you'll find the answer in this answer to a slightly different question: Generate "scatter plot" result of members against sets from SQL query
The answer uses Dynamic SQL. Check out the last link in mellamokb's answer: http://www.sqlfiddle.com/#!3/c136d/14 where he creates column names from row data.
In case you have a grouped flat data structure that you want to group transpose, like such:
GRP | ID
---------------
1 | 1234
1 | 1235
1 | 1236
1 | 1267
1 | 1278
2 | 1234
2 | 1235
2 | 1267
2 | 1289
And you want its group transposition to appear like:
GRP | Column 1 | Column 2 | Column 3 | Column 4 | Column 5
-------------------------------------------------------------
1 | 1234 | 1235 | 1236 | 1267 | 1278
2 | 1234 | 1235 | NULL | 1267 | NULL
You can accomplish it with a query like this:
SELECT
Column1.ID As column1,
Column2.ID AS column2,
Column3.ID AS column3,
Column4.ID AS column4,
Column5.ID AS column5
FROM
(SELECT GRP, ID FROM FlatTable WHERE ID = 1234) AS Column1
LEFT OUTER JOIN
(SELECT GRP, ID FROM FlatTable WHERE ID = 1235) AS Column2
ON Column1.GRP = Column2.GRP
LEFT OUTER JOIN
(SELECT GRP, ID FROM FlatTable WHERE ID = 1236) AS Column3
ON Column1.GRP = Column3.GRP
LEFT OUTER JOIN
(SELECT GRP, ID FROM FlatTable WHERE ID = 1267) AS Column4
ON Column1.GRP = Column4.GRP
LEFT OUTER JOIN
(SELECT GRP, ID FROM FlatTable WHERE ID = 1278) AS Column5
ON Column1.GRP = Column5.GRP
(1) This assumes you know ahead of time which columns you will want — notice that I intentionally left out ID = 1289 from this example
(2) This basically uses a bunch of left outer joins to append 1 column at a time, thus creating the transposition. The left outer joins (rather than inner joins) allow for some columns to be null if they don't have corresponding values from the flat table, without affecting any subsequent columns.

Resources