Hello I am little bit confused to see the sql server behaviour on executing the query. According to mine the output should be "Priyanka" ,4
Declare #temp table(
Name Varchar(50),
amount int
)
insert #temp values ('Priyanka' ,10 )
Update #temp
set amount=amount-A.a
from (
select 'Priyanka' as Name,1 as a
union
select 'Priyanka' as Name,5 as a
)A
where [#temp].Name in (A.Name)
select * from #temp
But
the output
Name amount
Priyanka 9
Can any one Please tell me why this is happened.
Standard SQL doesn't support a from clause with update and you'd instead have to write your access to other tables as a direct subquery in the set clause. If you did that, you'd get the error "subquery returned more than one value" and have some idea of the issue.
Unfortunately, the Microsoft extension to SQL that allows a FROM clause also silently ignores the fact that multiple rows may match, uses one of those rows and ignores the others.1
If you're going to use this extension, it's up to you to carefully ensure that you don't have multiple matches to a single row in the target table.
I'd rearrange your query, something like:
Declare #temp table(
Name Varchar(50),
amount int
)
insert #temp values ('Priyanka' ,10 )
;With A as
(
select 'Priyanka' as Name,1 as a
union
select 'Priyanka' as Name,5 as a
)
Update t
set amount=amount-Aa.a
from
#temp t
cross apply
(select SUM(a) as a from A where Name = t.Name) Aa
select * from #temp
Where I use the cross apply to aggregate the data down to a single row per target row.
1Importantly, though, it does support the concept that the effects of an UPDATE are applied "as if" all rows (and columns within them) are updated in parallel. So you don't get that first the update applies using one row and then the second update gets to update an already updated row.
You need to SUM the values of the union entries. Simply UNION the entries it have multiple entries so it may take any one entry and ignore the remains.
For your case the following query will work:
DECLARE #temp TABLE (NAME VARCHAR(50), amount INT)
INSERT #temp
VALUES ('Priyanka', 10)
UPDATE t
SET amount = t.amount - A.a
FROM #temp t
JOIN (
SELECT NAME, SUM(a) AS a FROM (
SELECT 'Priyanka' AS NAME, 1 AS a
UNION
SELECT 'Priyanka' AS NAME, 5 AS a
) c
GROUP BY NAME
) A ON A.NAME = t.NAME
SELECT * FROM #temp
Related
I have the following query in SQL Server. How do I get the number of rows of previous select query as following format?
Sample Query
select ID, Name FROM Branch
UNION ALL
SELECT ROWCOUNT_BIG(), ''
Sample Output
If you use a CTE you can count the rows and union all together:
with cte as (
select ID, [Name]
from dbo.Branch
)
select ID, [Name]
from cte
union all
select count(*) + 1, ''
from cte;
I think you want to see total count of the select statement. you can do this way.
CREATE TABLE #test (id int)
insert into #test(id)
SELECT 1
SELECT id from #test
union all
SELECT rowcount_big()
Note: Here, the ID will be implicitly converted to BIGINT datatype, based on the datatype precedence. Read more
Presumably, you are running this in some sort of application. So why not use ##ROWCOUNT?
select id, name
from . . .;
select ##rowcount_big; -- big if you want a bigint
I don't see value to including the value in the same query. However, if the underlying query is an aggregation query, there might be a way to do this using GROUPING SETS.
Here are two ways. It's better to use a CTE to define the row set so further table inserts don't interfere with the count. Since you're using ROWCOUNT_BIG() these queries use COUNT_BIG() (which also returns bigint) to count the inserted rows. In order to make sure the total always appears as the last row an 'order_num' column was added to the SELECT list and ORDER BY clause.
drop table if exists #tTest;
go
create table #tTest(
ID int not null,
[Name] varchar(10) not null);
insert into #tTest values
(115, 'Joe'),
(116, 'Jon'),
(117, 'Ron');
/* better to use a CTE to define the row set */
with t_cte as (
select *
from #tTest)
select 1 as order_num, ID, [Name]
from t_cte
union all
select 2 as order_num, count_big(*), ''
from t_cte
order by order_num, ID;
/* 2 separate queries could give inconsistent result if table is inserted into */
select 1 as order_num, ID, [Name]
from #tTest
union all
select 2 as order_num, count_big(*), ''
from #tTest
order by order_num, ID;
Both return
order_num ID Name
1 115 Joe
1 116 Jon
1 117 Ron
2 3
Thanks in advance !!
I want to get below data in separate table with column how can we achieved this.
From my reading of your question, you would like the results of that SELECT statement put into a new table?
Firstly, I'm assuming your original SQL works as a SELECT statement - e.g., all those tables have the same structure. Note that you can simplify the unions, but I haven't done so here, to keep the key part of the answer (saving the data) as the main focus.
To save the data into another table, you can either create a table first and make that into an insert, or just use 'SELECT INTO' within the main SELECT.
If you are happy with the columns being automatically created, the 'SELECT INTO' version will create columns (e.g., you do not need to specify the columns in a CREATE TABLE statement). However, when you run the SELECT INTO, it does create the table. Therefore if you want to insert further values, you need to specify the column list (or have matching column lists).
SELECT INTO version
select *
INTO #Temp -- Added This row
from
( select * from #OneyearExpiry
union all
select * from #OtherYearExpiry
) A
except
select * from
( select * from #ONEYRCON
union all
select * from #OTHERYRCON
) B
INSERT INTO version
CREATE TABLE #Temp (<your fields here to match the SELECT statement>)
INSERT INTO #Temp
select * from
( select * from #OneyearExpiry
union all
select * from #OtherYearExpiry
) A
except
select * from
( select * from #ONEYRCON
union all
select * from #OTHERYRCON
) B
Set operators are evaluated from top to bottom so there only needs to be 1 subquery. Something like this
select ab.* into #Temp
from (select * from #OneyearExpiry
union all
select * from #OtherYearExpiry
except
select * from #ONEYRCON
except
select * from #OTHERYRCON) ab;
I have a dataset in Excel where I have a few thousand id's. In a database I need a few columns to match these ids but some ids are listed twice in the Excel list (and they need to be there twice). I'm trying to write a query with an IN statement, but it automatically filters the duplicates. But I want the duplicates as well, otherwise I need to manually rearrange the data merge between the Excel and SQL results.
Is there any way to do something like
SELECT *
FROM table
WHERE id IN (
.. list of thousands ids
)
To also get the duplicates without using UNION ALL to prevent from firing thousands of seperate queries to the database?
You need to use a left join if you want to keep the duplicates. If the ordering is important, then you should include that information as well.
Here is one method:
select t.*
from (values (1, id1), (2, id2), . . .
) ids(ordering, id) left join
table t
on t.id = ids.id
order by ids.ordering;
An alternative is to load the ids into a temporary table with an identity column to capture the ordering:
# Create the table
create table #ids (
ordering int identity(1, 1) primary key,
id
);
# Insert the ids
insert into #ids (id)
select #id;
# Use them in the query
select t.*
from #ids ids left join
table t
on t.id = ids.id
order by ids.ordering;
If I understand this correctly this is exactly the way IN is supposed to work...
DECLARE #tbl TABLE(value INT, content VARCHAR(100));
WITH RunningNummber AS
(
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS Nmbr
FROM sys.objects
)
INSERT INTO #tbl
SELECT Nmbr,'Content for ' + CAST(Nmbr AS VARCHAR(100))
FROM RunningNummber;
--This ...
SELECT * FROM #tbl WHERE value IN(1,3,5);
-- ... is the same as this:
SELECT * FROM #tbl WHERE value IN(1,1,1,1,3,3,5,1,3,5);
If you want to combine two result-sets you have to join them...
In my opinion, I believe that is better that you import in a table the values corresponding with the list of thousands ids and apply a Subquery to get the information that you will need.
Even once time that you got all the ids in the target table you can filter with a T-SQL for deleting duplicates values and avoid any future problem.
I'll start directly by explaining with an example. Suppose I have a table which has 3 columns as shown.
Now what I am trying to achieve is, I want the first values of each individual column into a single column. So it would be something like this,
I have tried a few queries here including using TOP 1 and other incorrect ways. But I am still missing something here to achieve the exact output.
Need some guidance here on how to achieve this. Thank you.
SAMPLE TABLE
SELECT * INTO #TEMP
FROM
(
SELECT 1 BATCH_ID,'AAA' ASSIGNMENTTITLE,'FILE' ASSIGNMENTTYPE
UNION ALL
SELECT 1,'AAA1','FILE'
UNION ALL
SELECT 1,'AAA','FILE'
)TAB
If you need the second row specifically you can do the below
QUERY
;WITH CTE AS
(
-- Order row according to default format
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT(0))) RNO,*
FROM #TEMP
)
SELECT CAST(BATCH_ID AS VARCHAR(20)) FROM CTE WHERE RNO=2
UNION ALL
SELECT ASSIGNMENTTITLE FROM CTE WHERE RNO=2
UNION ALL
SELECT ASSIGNMENTTYPE FROM CTE WHERE RNO=2
Click here to view result
UPDATE
Since there are 3 items in each record, it can be puzzled unless and otherwise an a column is for each items in a record.
;WITH CTE AS
(
-- Order row according to default format
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT(0))) RNO,*
FROM #TEMP
)
SELECT CAST(BATCH_ID AS VARCHAR(20)),RNO
FROM CTE
UNION ALL
SELECT ASSIGNMENTTITLE,RNO
FROM CTE
UNION ALL
SELECT ASSIGNMENTTYPE,RNO
FROM CTE
ORDER BY RNO
Click here to view result
You can use the concat() function to create a column consisting of all the desired values
More info here
Simply you can try this. If want specific for a row use rowid. For all columns Use unpivot
create table #temp(id int, name varchar(100), title varchar(100))
insert into #temp values(1,'aaa','file')
insert into #temp values(1,'aaas','filef')
insert into #temp values(1,'aaaww','filefs')
select * from #temp
select top 1 cast(id as varchar) title from #temp
union
select top 1 name from #temp
union
select top 1 title from #temp
drop table #temp
This might help you
select top 1 convert(varchar(10), batch_id) ASSIGNMENTTITLE from table
union all
select top 1 ASSIGNMENTTITLE from table
union all
select top 1 ASSIGNMENTTYPE from table
If this is really what you want: "I want the first values of each individual column into a single column" it would be:
select ASSIGNMENTTITLE
from (
select min(convert(varchar(10), batch_id)) ASSIGNMENTTITLE,
1 ColOrder from table
union all
select min(ASSIGNMENTTITLE),
2 ColOrder from table
union all
select min(ASSIGNMENTTYPE),
3 ColOrder from table
) as data
order by ColOrder
This question already has answers here:
Delete duplicate records in SQL Server?
(10 answers)
Closed 9 years ago.
I currently have a URL redirect table in my database that contains ~8000 rows and ~6000 of them are duplicates.
I was wondering if there was a way I could delete these duplicates based on a certain columns value and if it matches, I am looking to use my "old_url" column to find duplicates and I have used
SELECT old_url
,DuplicateCount = COUNT(1)
FROM tbl_ecom_url_redirect
GROUP BY old_url
HAVING COUNT(1) > 1 -- more than one value
ORDER BY COUNT(1) DESC -- sort by most duplicates
however I'm not sure what I can do to remove them now as I don't want to lose every single one, just the duplicates. They are almost a match completely apart from sometimes the new_url is different and the url_id (GUID) is different in each time
In my opinion ranking functions and a CTE are the easiest approach:
WITH CTE AS
(
SELECT old_url
,Num = ROW_NUMBER()OVER(PARTITION BY old_url ORDER BY DateColumn ASC)
FROM tbl_ecom_url_redirect
)
DELETE FROM CTE WHERE Num > 1
Change ORDER BY DateColumn ASC accordingly to determine which records should be deleted and which record should be left alone. In this case i delete all newer duplicates.
If your table has a primary key then this is easy:
BEGIN TRAN
CREATE TABLE #T(Id INT, OldUrl VARCHAR(MAX))
INSERT INTO #T VALUES
(1, 'foo'),
(2, 'moo'),
(3, 'foo'),
(4, 'moo'),
(5, 'foo'),
(6, 'zoo'),
(7, 'foo')
DELETE FROM #T WHERE Id NOT IN (
SELECT MIN(Id)
FROM #T
GROUP BY OldUrl
HAVING COUNT(OldUrl) = 1
UNION
SELECT MIN(Id)
FROM #T
GROUP BY OldUrl
HAVING COUNT(OldUrl) > 1)
SELECT * FROM #T
DROP TABLE #T
ROLLBACK
this is the sample to delete multiple record with guid, hope it can help u=)
DECLARE #t1 TABLE
(
DupID UNIQUEIDENTIFIER,
DupRecords NVARCHAR(255)
)
INSERT INTO #t1 VALUES
(NEWID(),'A1'),
(NEWID(),'A1'),
(NEWID(),'A2'),
(NEWID(),'A1'),
(NEWID(),'A3')
so now, a duplicated record with guid is created in #t1
;WITH CTE AS(
SELECT DupID,DupRecords, Rn = ROW_NUMBER()
OVER (PARTITION BY DupRecords ORDER BY DupRecords)
FROM #t1
)
DELETE FROM #t1 WHERE DupID IN (SELECT DupID FROM CTE WHERE RN>1)
with query above, duplicated record is deleted from #t1, i use Row_number() to distinct each of the records
SELECT * FROM #t1