Sum data and merge results by updating table - sql-server

I have a table with the following data:
Table1
UniqueKey
Text A
Text B
Value 1
Value 2
Key1
ABC
ABC
2
3
Key2
DEF
GHI
3
4
Key3
STE
GGE
5
5
Key2
DEF
GHI
3
4
Key2
DEF
GHI
5
7
Key1
ABC
ABC
3
7
Using the key UniqueKey I want to add the values in the columns Value 1 and Values 2 so that each Unique Key exists only once in my table.
The Table1 should then look like this:
UniqueKey
Text A
Text B
Value 1
Value 2
Key1
ABC
ABC
5
10
Key2
DEF
GHI
11
15
Key3
STE
GGE
5
5
I have already made the following considerations. I can use the group by and sum command to add the columns as desired.
I have trouble saving these changes in the table and deleting the redundant columns. So far I have only used the merge command on two different tables.
SELECT UniqueKey, SUM(Value1) Value1, SUM(Value2) Value2
FROM Table1
GROUP BY UniqueKey
Has anyone an idea?

You can create a new table with the current query
SELECT [UniqueKey], [Text A], [Text B], SUM([Value 1]) AS Value1, SUM([Value 2]) AS Value2
INTO Table2
FROM Table1
GROUP BY [UniqueKey], [Text A], [Text B]
drop the original source
DROP TABLE Table1
rename new one to the original
sp_rename 'Table2', 'Table1'
and add a primary key on UniqueKey column to enforce uniqueness as the last step
ALTER TABLE Table1 ADD PRIMARY KEY (UniqueKey);

You will need to group by the columns the other 2 columns Text A and Text B.
SELECT UniqueKey, [Text A], [Text B], SUM([Value 1]) AS Val1, SUM([Value 2]) AS Val2
FROM Table1
GROUP BY UniqueKey, [Text A], [Text B]
If you want to get this data into Table1, you can save the result of the query above in a temp table, delete the data in Table1, then re-insert the data from the temp table into Table1.
-- Check if you have a temp table #Table1, if so drop it
IF OBJECT_ID('tempdb..#Table1') IS NOT NULL
BEGIN
DROP TABLE #Table1
END
GO
-- Save the data into temp table #Table1
SELECT UniqueKey, [Text A], [Text B], SUM([Value 1]) AS Val1, SUM([Value 2]) AS Val2 INTO #Table1
FROM Table1
GROUP BY UniqueKey, [Text A], [Text B]
GO
-- Delete the data in Table1
DELETE FROM Table1
GO
-- Re-insert the data from the temp table #Table1 into Table1
INSERT INTO Table1 (UniqueKey, [Text A], [Text B], [Value 1], [Value 2])
SELECT UniqueKey, [Text A], [Text B], [Value 1], [Value 2]
FROM #Table1
GO

Related

Exclude row based in multiple column value

i need to exclude rows based multiple column conditions like 1) first find value "rev" from column ID1, 2) find the corresponding value in column ID2 based on 1st condition i.e. Ref1, and exclude all the rows contains the value in the 2nd column.
ID1 ID2 VALUE
post Ref1 12
post Ref1 3
rev Ref1 12
rev Ref1 3
post Ref2 10
post Ref2 5
output
ID1 ID2 VALUE
post Ref2 10
post Ref2 5
This assumes that "rev" stands for reversal or something similar, and that if the ID2 and VALUE are the same for a "post" and a "rev" they negate each other.
I created your table with this:
DROP TABLE IF EXISTS #table1;
CREATE TABLE #Table1 (ID1 VARCHAR(4), ID2 VARCHAR(4), VALUE INT);
INSERT INTO #Table1 (ID1, ID2, VALUE)
VALUES ('post', 'Ref1', 12),
('post', 'Ref1', 3),
('rev', 'Ref1', 12),
('rev', 'Ref1', 3),
('post', 'Ref2', 10),
('post', 'Ref2', 5);
I've then written this query to initially fetch all the 'post' rows of data, then self join matching on ID2 and VALUE and that ID1 now has to be 'rev', then in the WHERE clause adding something to only return rows where there is no T2.ID1
SELECT T1.ID1,
T1.ID2,
T1.VALUE
FROM #Table1 AS T1
LEFT JOIN #Table1 AS T2 ON T2.ID2 = T1.ID2 AND T2.VALUE = T1.VALUE AND T2.ID1 = 'rev'
WHERE T1.ID1 = 'post' AND T2.ID1 IS NULL;
You can first select all rows having ID1 = 'post' then remove all records having ID1 = 'rev', when 'rev' is replaced with 'post'.
SELECT * FROM tab WHERE [ID1] = 'post'
EXCEPT
SELECT 'post' AS [ID1], [ID2], [VALUE] FROM tab WHERE [ID1] = 'rev'
Check the demo here.

Selecting Columns A values if no like a value in column B in SQL Server

I have Table1
And I am trying to remove every identical Column A value if one of it's row has "ZX" anywhere in Column B. So if I did it right, it will look like Table2
I did the following:
Select
Column A,
Column B
From
Table1
Where
Column B not like '%ZX%'
However, it only removes rows with ZX and not every identical Column A values and returns this Table instead
I will really appreciate any help on this! Thank you in advance :)
You can use NOT IN
SELECT
ColumnA
, ColumnB
FROM table1
WHERE ColumnA NOT IN (SELECT ColumnA FROM table1 WHERE ColumnB like '%ZX%')
I like not exists for this purpose:
Select t1.*
From Table1 T1
where not exists (select 1 from table1 tt1 where tt1.a = t1.a and tt1.b like '%ZX%');
This can take advantage of an index on table1(a, b).
Use :NOT EXISTS and that should do it:
Select
[Column A],
[Column B]
From Table1 T1
where
NOT EXISTS (
SELECT 1 FROM TABLE1 T2
WHERE T2.[Column B] like '%ZX%'
AND T2.[column a] = t1.[column a]
)

SQL Server unpivot two columns

I'm trying to pivot a table to get 3 columns
my example table is like :
CREATE TABLE tbl1 (A1 int, cA1 int,A2 int, cA2 int,A3 int, cA3 int)
GO
INSERT INTO tbl1 VALUES (60,2,30,3,10,5);
GO
I am using the query below to get tthe results from two columns:
select A, value from tbl1
unpivot
(
value
for A in ([A1], [A2],[A3])
) un1;
The results are like :
A | value
--+-------
A1|60
A2|30
A3|10
but I want to add and second column with and the results to be like :
A | value1 | value2
--+--------+--------
A1| 60 | 2
A2| 30 | 3
A3| 10 | 5
Any Help??
I would use APPLY:
select v.*
from tbl1 t cross apply
(values ('A1', t.A1, t.cA1),
('A2', t.A2, t.cA2),
('A3', t.A3, t.cA3)
) v(A, value1, value2);
CROSS APPLY implements a lateral join. This is much more powerful than merely unpivoting data, although unpivoting data is one simple way to start learning about lateral joins.
Another way with XML:
DECLARE #x xml = (SELECT * FROM tbl1 as t FOR XML AUTO, TYPE)
;WITH cte AS (
SELECT CAST(t.c.query('local-name(.)') as nvarchar(10)) as [name],
t.c.value('.','int') as [value],
p.number as [pos]
FROM [master]..spt_values p
CROSS APPLY #x.nodes('/t[position()=sql:column("number")]/#*') as t(c)
WHERE p.[type] = 'p'
)
SELECT c.[name] as A,
c.[value] as value1,
c1.[value] as value2
FROM cte c
INNER JOIN cte c1
ON c1.[name] = N'c'+c.[name] and c.pos = c1.pos
Output:
A value1 value2
A1 60 2
A2 30 3
A3 10 5

Google BigQuery: Table join with REPEATED RECORD values

I have a table like this:
Row field1 field2 field3.a field3.b
1 value1 1 id1 key5
id2 key6
2 value2 2 id3 key7
id4 key8
The first 2 columns are standard fields, the third column is a REPEATED RECORD field.
I have 2 additional tables
Row id value
1 id1 my-valueA
2 id2 my-valueB
3 id3 my-valueC
4 id4 my-valueD
and
Row id value
1 key5 my-valueE
2 key6 my-valueF
3 key7 my-valueG
4 key8 my-valueH
Which map the a id/key from the first table (I used the term key and id to avoid confusion, but at the end the concept is the same) with a given value
Here is a full statement to reproduce the structure
#standardSQL
WITH my_table AS (
SELECT "value1" as field1, 1 as field2, [STRUCT("id1" as a, "key5" as b),STRUCT("id2" as a, "key6" as b)] as field3
UNION ALL
SELECT "value2" as field2, 2 as field2, [STRUCT("id3" as a, "key7" as b),STRUCT("id4" as a, "key8" as b)] as field3
),
ids_table AS (
SELECT "id1" as id, "my-valueA" as value
UNION ALL
SELECT "id2" as id, "my-valueB" as value
UNION ALL
SELECT "id3" as id, "my-valueC" as value
UNION ALL
SELECT "id4" as id, "my-valueD" as value
),
keys_table AS (
SELECT "key5" as id, "my-valueE" as value
UNION ALL
SELECT "key6" as id, "my-valueF" as value
UNION ALL
SELECT "key7" as id, "my-valueG" as value
UNION ALL
SELECT "key8" as id, "my-valueH" as value
)
-- SELECT * FROM my_table
-- SELECT * FROM ids_table
-- SELECT * FROM keys_table
My goal is to replace the key/id values from the first tables with the value given by the 2 other tables, like a classic join on id.
Here is the expected output
Row field1 field2 t2_value t3_value
1 value1 1 my-valueA my-valueE
my-valueB my-valueF
2 value2 2 my-valueC my-valueG
my-valueD my-valueH
At first I thought about using UNNEST operator to obtain flat lines, so a simple JOIN can be made to resolve the value and after that rejoin the array with the replaced values.
SELECT my_table.* EXCEPT(field3),
t2.value as t2_value,
t3.value as t3_value
FROM my_table CROSS JOIN UNNEST(my_table.field3) AS t1
LEFT JOIN ids_table AS t2 ON t1.a = t2.id
LEFT JOIN keys_table as t3 ON t1.b = t3.id
With this statement the values are properly replace from the id to the value, but now I'm unable to reproduce the RECORD REPEATED structure of before
Below is for BigQuery Standard SQL
#standardSQL
WITH my_table AS (
SELECT "value1" AS field1, 1 AS field2, [STRUCT("id1" AS a, "key5" AS b),STRUCT("id2" AS a, "key6" AS b)] AS field3 UNION ALL
SELECT "value2" AS field2, 2 AS field2, [STRUCT("id3" AS a, "key7" AS b),STRUCT("id4" AS a, "key8" AS b)] AS field3
), ids_table AS (
SELECT "id1" AS id, "my-valueA" AS value UNION ALL
SELECT "id2" AS id, "my-valueB" AS value UNION ALL
SELECT "id3" AS id, "my-valueC" AS value UNION ALL
SELECT "id4" AS id, "my-valueD" AS value
),keys_table AS (
SELECT "key5" AS id, "my-valueE" AS value UNION ALL
SELECT "key6" AS id, "my-valueF" AS value UNION ALL
SELECT "key7" AS id, "my-valueG" AS value UNION ALL
SELECT "key8" AS id, "my-valueH" AS value
)
SELECT
field1, field2,
(
SELECT ARRAY_AGG(STRUCT<a_value STRING, b_value STRING>(t2.value, t3.value))
FROM UNNEST(field3) t1
LEFT JOIN ids_table AS t2 ON t1.a = t2.id
LEFT JOIN keys_table AS t3 ON t1.b = t3.id
) AS field3
FROM my_table
with below output
field1 field2 field3.a_value field3.b_value
value1 1 my-valueA my-valueE
my-valueB my-valueF
value2 2 my-valueC my-valueG
my-valueD my-valueH

Update table gives primary key violation error

I have following tow tables
create table #temp(id int,rid int)
insert into #temp
select 1,1
union all
select 2,1
union all
select 3,1
select * from #temp
drop table #temp1
create table #temp1(id int, nid int,PRIMARY KEY CLUSTERED
(
id asc,nid asc
))
insert into #temp1
select 1,10
union all
select 2,10
union all
select 2,11
union all
select 3,10
Following are the both result sets:
id rid
1 1
2 1
3 1
id nid
1 10
2 10
2 11
3 10
I want to update #temp1 table with value from rid field of #temp table by matching id field from both tables. See following query:
select a.*
from #temp1 a inner join #temp b
on a.id = b.id
where a.id <> b.rid
It returns:
id nid
2 10
2 11
3 10
I want to update id with following query:
update a
set a.id = b.rid
-- select a.*
from #temp1 a inner join #temp b
on a.id = b.id
where a.id <> b.rid
But it returns
primary key violation error because of primary key in table #temp1.
I would like to delete the value if it is already exist if not then I would like to update
for example
id nid
1 10
2 10-- want to update but not able to this bcoz it violates primary key so delete this row.
2 11-- able to update this row but other 2 rows causing an issue.
3 10-- want to update but not able to this bcoz it violates primary key so delete this row.
Please suggest other ways to do this.
Because You are Violating the Primary Key Constraints
Check Below Tables
select B.*
from #temp1 a inner join #temp b
on a.id = b.id
where a.id <> b.rid
id rid
2 1
2 1
3 1
select * from #temp1
id nid
1 10
2 10
2 11
3 10
You are setting ID of above first table using join from #temp which already in #temp1
You Are attempt to Update Values which are already in #temp1 where id=2,2,3
select *
from #temp1 a inner join #temp b
on a.id = b.id
where a.id <> b.rid
You would be updating two id 2 records to the same value. You cannot do this, period. There is no other method to fix this except to drop the PK which I would suggest would be bad idea.
It is possible you need some further definition in your pdate to specify which of multiple records you want to update or you may need to delete the record which might end up as a duplicate before you do the update. Not knowing the business rules for what you are actually trying to accomplish or what your data means, it is impossiblet say what you can do to solve your problem. This ia case where the solution is dependant on the meaning and of course we have no meaning here.

Resources