Find Query in SQL Server for the below Results - sql-server

I have table look like the following
Col1
Col2(nvarchar)
Col3
1
2/4
100
1 ​
2/4
200
2 ​
1/3
140
3 ​
2/3
120
4
3/4
200
Result would be:
The sum of column 3 group by column 1 + column 3 of 2 and column 3 of 4
(excluding the / from col 2)
For example, 1st row will be 100 + 200 + 140 + 200 = 640.
Result would be like the following:
Col1
Sum
1
640
2
560
3
380
4
520
How can I make or what would be the query in sql server to get such resultant one?

Try something like this:
DECLARE #data table ( Col1 int, Col2 nvarchar(3), Col3 int );
INSERT INTO #data VALUES
( 1, '2/4', 100 ),
( 1, '2/4', 200 ),
( 2, '1/3', 140 ),
( 3, '2/3', 120 ),
( 4, '3/4', 200 );
;WITH cte AS (
SELECT
Col1, Col2, SUM ( Col3 ) AS Col3Sum
FROM #data AS d
GROUP BY
Col1, Col2
)
SELECT
Col1, ( Col3Sum + Col2MatchesSum ) AS [Sum]
FROM cte
OUTER APPLY (
-- get the sum of rows matching Col2 delimited values.
SELECT SUM ( Col3 ) AS Col2MatchesSum FROM #data WHERE Col1 IN (
SELECT CAST ( [value] AS int ) FROM STRING_SPLIT ( cte.Col2, '/' )
)
) AS n
ORDER BY
Col1;
RETURNS
+------+-----+
| Col1 | Sum |
+------+-----+
| 1 | 640 |
| 2 | 560 |
| 3 | 380 |
| 4 | 520 |
+------+-----+

Related

Query to retain latest non-zero value

I'm using SQL Server 2016 and have a table with the following data:
PlaySeq
TransMaxValue
1
250
2
500
3
0
4
400
5
0
6
300
7
500
8
0
9
0
I'm trying to construct a query that adds a column TransMaxValueContd to that dataset.
That TransMaxValueContd column should retain the last non-zero value encountered in column TransMaxValue.
Ordering is done by PlaySeq.
My expected result from the query is this:
PlaySeq
TransMaxValue
TransMaxValueContd
1
250
250
2
500
500
3
0
500
4
400
400
5
0
400
6
300
300
7
500
500
8
0
500
9
0
500
I've been using windowing functions like LAST_VALUE() and LAG(), but can't seem to get the results right.
Maybe I'm overcomplicating it.
Does anyone know how to do this?
ps: I'm just looking for the query. No need to modify the source table.
Edit: Added a SQLFiddle example with a failed attempt, which is:
SELECT a.PlaySeq,
a.TransMaxValue,
IIF(ISNULL(LAG(a.TransMaxValue,1) OVER (ORDER BY a.PlaySeq), a.TransMaxValue) = a.TransMaxValue, a.TransMaxValue, LAG(a.TransMaxValue,1) OVER (ORDER BY a.PlaySeq)) AS TransMaxValueContd
FROM myTable AS a;
Edit: Thank you for all the answers, which provided new useful insights!
I ended up using this, inspired by the answer from SteveC.
SELECT a.PlaySeq,
a.TransMaxValue,
(SELECT TOP 1 x.TransMaxValue
FROM myTable AS x
WHERE x.PlaySeq <= a.PlaySeq
AND x.TransMaxValue != 0
ORDER BY x.PlaySeq DESC) AS TransMaxValueContd
FROM myTable AS a;
A simple way could use OUTER APPLY and SELECT TOP(1). Something like this
select m.PlaySeq, m.[TransMaxValue],
case when m.[TransMaxValue]=0
then oa.TransMaxValue
else m.TransMaxValue end TransMaxValueContd
from myTable m
outer apply (select top(1) mm.[TransMaxValue]
from myTable mm
where m.PlaySeq>mm.PlaySeq
and mm.[TransMaxValue]>0
order by mm.PlaySeq desc) oa;
PlaySeq TransMaxValue TransMaxValueContd
1 250 250
2 500 500
3 0 500
4 400 400
5 0 400
6 300 300
7 500 500
8 0 500
9 0 500
Perhaps this will help:
DECLARE #Tab TABLE(PlaySeq INT, TransMaxValue INT)
INSERT #Tab
VALUES(1,250),(2,500),(3,0),(4,400),(5,0)
,(6,300),(7,500),(8,0),(9,0)
SELECT PlaySeq,
TransMaxValue,
FIRST_VALUE(TransMaxValue) OVER(PARTITION BY Grp ORDER BY PlaySeq) AS TransMaxValueContd
FROM (
SELECT
PlaySeq,
TransMaxValue,
SUM(CASE WHEN TransMaxValue = 0 THEN 0 ELSE 1 END) OVER(ORDER BY PlaySeq) AS Grp
FROM #Tab
) AS tbl
ORDER BY PlaySeq
Please try the following solution.
It is based on Windows function ROW_NUMBER() and non-equal relationship clause:
FROM #tbl AS t1 INNER JOIN
#tbl AS t2 ON t1.PlaySeq > t2.PlaySeq
SQL
-- DDL and sample data population, start
DECLARE #tbl TABLE (PlaySeq INT, TransMaxValue INT);
INSERT INTO #tbl (PlaySeq, TransMaxValue) VALUES
(1, 250),
(2, 500),
(3, 0 ),
(4, 400),
(5, 0 ),
(6, 300),
(7, 500),
(8, 0 ),
(9, 0 );
-- DDL and sample data population, end
;WITH rs AS
(
SELECT t1.*
, t2.TransMaxValue AS prev_value
, ROW_NUMBER() OVER (PARTITION BY t1.PlaySeq ORDER BY t2.PlaySeq DESC) AS seq
FROM #tbl AS t1 INNER JOIN
#tbl AS t2 ON t1.PlaySeq > t2.PlaySeq
WHERE t2.TransMaxValue > 0
)
SELECT PlaySeq, TransMaxValue, TransMaxValue AS TransMaxValueContd
FROM #tbl WHERE PlaySeq = 1
UNION ALL
SELECT PlaySeq, TransMaxValue, IIF(TransMaxValue > 0, TransMaxValue, prev_value) AS TransMaxValueContd
FROM rs
WHERE seq = 1
ORDER BY PlaySeq ASC;
Output
+---------+---------------+--------------------+
| PlaySeq | TransMaxValue | TransMaxValueContd |
+---------+---------------+--------------------+
| 1 | 250 | 250 |
| 2 | 500 | 500 |
| 3 | 0 | 500 |
| 4 | 400 | 400 |
| 5 | 0 | 400 |
| 6 | 300 | 300 |
| 7 | 500 | 500 |
| 8 | 0 | 500 |
| 9 | 0 | 500 |
+---------+---------------+--------------------+
There may be a better way, but you could try using correlated subqueries:
SELECT q.PlaySeq, q.TransMaxValue
, (CASE
WHEN q.TransMaxValue <> 0 THEN q.TransMaxValue
ELSE (SELECT d.TransMaxValue FROM myTable d WHERE d.PlaySeq = q.PlaySeqRef)
END) TransMaxValueContd
FROM (
SELECT PlaySeq
, TransMaxValue
, (SELECT MAX(PlaySeq)
FROM myTable b
WHERE b.PlaySeq < a.PlaySeq
AND b.TransMaxValue <> 0) PlaySeqRef
FROM myTable a) q;

“Stuff and 'For Xml Path'” or UNION to exclude duplicate rows

This is further progress of question here: how to use "Stuff and 'For Xml Path'" to unite rows in table
I have 3 tables - invoices, positions and accounts which build common table by SELECT as specified in result below. I need to exclude duplicate rows which appear due to different accounts for same invoices. I think it can be solved by “Stuff and 'For Xml Path'” and/or by UNION, but I don't really know how to do that.
Please assist with this issue. Thank You in advance.
Here's dbfiddle with DL and sample data population: https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=6401c2886a24b21239dade27e8c549ec
Using DevExpress dashboard designer based on SQL Server 2016.
Query:
-- DDL and sample data population, start
CREATE TABLE invoices
(
invoice VARCHAR(20) NOT NULL,
id INT NOT NULL,
);
INSERT invoices(invoice, id)
VALUES ('ty20210110', 1);
INSERT invoices(invoice, id)
VALUES ('ty20210111', 2);
INSERT invoices(invoice, id)
VALUES ('ty20210112', 3);
CREATE TABLE positions
(
position VARCHAR(20) NOT NULL,
quantity INT NOT NULL,
price INT NOT NULL,
summ INT NOT NULL,
invoice INT NOT NULL,
);
INSERT positions(position, quantity, price, summ, invoice)
VALUES ('p1000001', 2, 100, 200, 1);
INSERT positions(position, quantity, price, summ, invoice)
VALUES ('p1000002', 3, 100, 300, 2);
INSERT positions(position, quantity, price, summ, invoice)
VALUES ('p1000003', 1, 250, 250, 2);
INSERT positions(position, quantity, price, summ, invoice)
VALUES ('p1000004', 2, 120, 240, 1);
INSERT positions(position, quantity, price, summ, invoice)
VALUES ('p1000005', 4, 100, 400, 1);
INSERT positions(position, quantity, price, summ, invoice)
VALUES ('p1000006', 3, 100, 300, 1001);
INSERT positions(position, quantity, price, summ, invoice)
VALUES ('p1000007', 5, 80, 400, 3);
INSERT positions(position, quantity, price, summ, invoice)
VALUES ('p1000008', 5, 100, 500, 3);
CREATE TABLE accounts
(
account INT NOT NULL,
invoice INT NOT NULL,
);
INSERT accounts(account, invoice)
VALUES (01, 2);
INSERT accounts(account, invoice)
VALUES (02, 2);
INSERT accounts(account, invoice)
VALUES (03, 1);
INSERT accounts(account, invoice)
VALUES (04, 3);
INSERT accounts(account, invoice)
VALUES (05, 1);
INSERT accounts(account, invoice)
VALUES (06, 3);
-- DDL and sample data population, end
SELECT
positions.position, positions.quantity, positions.price, positions.summ,
invoices.invoice,
accounts.account
FROM
positions
INNER JOIN
invoices invoices ON invoices.id = positions.invoice
INNER JOIN
accounts accounts ON invoices.id = accounts.invoice
Result:
position
quantity
price
summ
invoice
account
p1000001
2
100
200
in20210110
3
p1000001
2
100
200
in20210110
5
p1000002
3
100
300
in20210111
1
p1000002
3
100
300
in20210111
2
p1000003
1
250
250
in20210111
1
p1000003
1
250
250
in20210111
2
p1000004
2
120
240
in20210110
3
p1000004
2
120
240
in20210110
5
p1000005
4
100
400
in20210110
3
p1000005
4
100
400
in20210110
5
p1000006
3
100
300
in20210110
3
p1000006
3
100
300
in20210110
5
p1000007
5
80
400
in20210112
4
p1000007
5
80
400
in20210112
6
p1000008
5
100
500
in20210112
4
p1000008
5
100
500
in20210112
6
Required result 1:
position
quantity
price
summ
invoice
account
p1000001
2
100
200
in20210110
3, 5
p1000004
2
120
240
in20210110
3, 5
p1000005
4
100
400
in20210110
3, 5
p1000006
3
100
300
in20210110
3, 5
p1000002
3
100
300
in20210111
1, 2
p1000003
1
250
250
in20210111
1, 2
p1000007
5
80
400
in20210112
4, 6
p1000008
5
100
500
in20210112
4, 6
Required result 2:
position
quantity
price
summ
invoice
account 1
account 2
p1000001
2
100
200
in20210110
3
5
p1000004
2
120
240
in20210110
3
5
p1000005
4
100
400
in20210110
3
5
p1000006
3
100
300
in20210110
3
5
p1000002
3
100
300
in20210111
1
2
p1000003
1
250
250
in20210111
1
2
p1000007
5
80
400
in20210112
4
6
p1000008
5
100
500
in20210112
4
6
Your first resultset can be handled in two ways, depending on your version of SQL Server. Try the following examples in SSMS:
Create Data
DECLARE #invoices table (
invoice VARCHAR(20) NOT NULL, id INT NOT NULL
);
INSERT INTO #invoices (invoice, id) VALUES
( 'ty20210110', 1 ), ( 'ty20210111', 2 ), ( 'ty20210112', 3 );
DECLARE #positions table (
position VARCHAR(20) NOT NULL, quantity INT NOT NULL, price INT NOT NULL, summ INT NOT NULL, invoice INT NOT NULL
);
INSERT INTO #positions ( position, quantity, price, summ, invoice ) VALUES
( 'p1000001', 2, 100, 200, 1 ),
( 'p1000002', 3, 100, 300, 2 ),
( 'p1000003', 1, 250, 250, 2 ),
( 'p1000004', 2, 120, 240, 1 ),
( 'p1000005', 4, 100, 400, 1 ),
( 'p1000006', 3, 100, 300, 1 ),
( 'p1000007', 5, 80, 400, 3 ),
( 'p1000008', 5, 100, 500, 3 );
DECLARE #accounts table (
account INT NOT NULL, invoice INT NOT NULL
);
INSERT INTO #accounts ( account, invoice ) VALUES
( 1, 2 ), ( 2, 2 ), ( 3, 1 ), ( 4, 3 ), ( 5, 1 ), ( 6, 3 );
If you're using SQL Server 2017+
SELECT
positions.position,
positions.quantity,
positions.price,
positions.summ,
invoices.invoice,
STRING_AGG ( accounts.account, ',' ) AS account
FROM #positions positions
INNER JOIN #invoices invoices
ON invoices.id = positions.invoice
INNER JOIN #accounts accounts
ON invoices.id = accounts.invoice
GROUP BY
position, quantity, price, summ, invoices.invoice
ORDER BY
invoice;
For Pre-SQL Server 2017
SELECT
positions.position,
positions.quantity,
positions.price,
positions.summ,
invoices.invoice,
acct.account
FROM #positions positions
INNER JOIN #invoices invoices
ON invoices.id = positions.invoice
INNER JOIN #accounts accounts
ON invoices.id = accounts.invoice
OUTER APPLY (
SELECT STUFF ( (
SELECT ',' + CAST ( a.account AS varchar(50) ) AS "text()"
FROM #accounts a
WHERE
a.invoice = invoices.id
FOR XML PATH ( '' )
), 1, 1, '' ) AS account
) AS acct
GROUP BY
position, quantity, price, summ, invoices.invoice, acct.account
ORDER BY
invoice;
Both queries return
+----------+----------+-------+------+------------+---------+
| position | quantity | price | summ | invoice | account |
+----------+----------+-------+------+------------+---------+
| p1000001 | 2 | 100 | 200 | ty20210110 | 3,5 |
| p1000004 | 2 | 120 | 240 | ty20210110 | 3,5 |
| p1000005 | 4 | 100 | 400 | ty20210110 | 3,5 |
| p1000006 | 3 | 100 | 300 | ty20210110 | 3,5 |
| p1000002 | 3 | 100 | 300 | ty20210111 | 1,2 |
| p1000003 | 1 | 250 | 250 | ty20210111 | 1,2 |
| p1000007 | 5 | 80 | 400 | ty20210112 | 4,6 |
| p1000008 | 5 | 100 | 500 | ty20210112 | 4,6 |
+----------+----------+-------+------+------------+---------+
The second resultset you requested gets considerably more complicated and requires the use of the XML datatype. The following example makes liberal assumptions of your data, most notably that only two accounts are expected. Having said that, you can expand the [account n] columns in the PIVOT as necessary without having to resort to dynamic SQL.
SELECT DISTINCT
positions.position,
positions.quantity,
positions.price,
positions.summ,
invoices.invoice
, x.*
FROM #positions positions
INNER JOIN #invoices invoices
ON invoices.id = positions.invoice
INNER JOIN #accounts accounts
ON invoices.id = accounts.invoice
OUTER APPLY (
-- Create an XML account list --
SELECT CAST ( (
SELECT
'account ' + CAST ( ROW_NUMBER() OVER ( ORDER BY a.invoice ) AS varchar(50) ) AS id,
a.account
FROM #accounts a
WHERE
a.invoice = invoices.id
FOR XML PATH ( 'data' ), ROOT ( 'accounts' )
) AS xml ) AS account_xml
) AS acct
OUTER APPLY (
-- PIVOT the account details --
SELECT
*
FROM (
SELECT
x.f.value( 'id[1]', 'varchar(50)' ) AS id,
x.f.value( 'account[1]', 'varchar(50)' ) AS act
FROM acct.account_xml.nodes( '//accounts/data' ) x(f)
) AS d
PIVOT (
MAX ( act ) FOR id IN ( [account 1], [account 2] )
) AS p
) AS x
ORDER BY
invoice;
Returns
+----------+----------+-------+------+------------+-----------+-----------+
| position | quantity | price | summ | invoice | account 1 | account 2 |
+----------+----------+-------+------+------------+-----------+-----------+
| p1000001 | 2 | 100 | 200 | ty20210110 | 3 | 5 |
| p1000004 | 2 | 120 | 240 | ty20210110 | 3 | 5 |
| p1000005 | 4 | 100 | 400 | ty20210110 | 3 | 5 |
| p1000006 | 3 | 100 | 300 | ty20210110 | 3 | 5 |
| p1000002 | 3 | 100 | 300 | ty20210111 | 1 | 2 |
| p1000003 | 1 | 250 | 250 | ty20210111 | 1 | 2 |
| p1000007 | 5 | 80 | 400 | ty20210112 | 4 | 6 |
| p1000008 | 5 | 100 | 500 | ty20210112 | 4 | 6 |
+----------+----------+-------+------+------------+-----------+-----------+

Sum one column and subtract over second column

I want to display the subtraction of two columns. From the first column I need to get sum all value and substract with each value from the second column.
This is the table structure:
id | name | col1 | col2 | date
------------------------------------
432| xxx | 0 | 15 |2015-11-17
432| yyy | 10 | 30 |2015-11-19
432| zzz | 60 | 40 |2015-11-20
433| aaa | 0 | 60 |2015-11-17
433| bbb | 80 | 20 |2015-11-19
433| ccc | 60 | 10 |2015-11-20
Formula should go:
sum(col1) = 70 =>>> WHERE ID = 432
70 - col2 col3
-------------------------
=> 70 - 15 = 55
=> 70 - (30 + 15) = 25
=> 70 - (40 + 45) = -15
---------------------------
sum(col1) = 140 ===>> WHERE ID = 433
140 - col2 col3
-------------------------
=> 140 - 60 = 80
=> 140 - (60 + 20) = 60
=> 140 - (10 + 80) = 50
result is col3 and Output should be like as
id | name | col1 | col2 | col3 | date
-------------------------------------------
432| xxx | 0 | 15 | 55 | 2015-11-17
432| yyy | 10 | 30 | 25 | 2015-11-19
432| zzz | 60 | 40 | -15 | 2015-11-20
433| aaa | 0 | 60 | 80 | 2015-11-17
433| bbb | 80 | 20 | 60 | 2015-11-19
433| ccc | 60 | 10 | 50 | 2015-11-20
EDIT: What if I need the values ​​vary depending on the group as a 432 and 433 id column.
Schema Info
DECLARE #TEST TABLE
(
id INT,
name VARCHAR(10),
col1 INT,
col2 int
)
INSERT INTO #TEST VALUES
(432,'xxx',0, 15 ),
(432,'yyy',10, 30 ),
(432,'zzz',60, 40 ),
(433,'aaa',0, 60 ),
(433,'bbb',80, 20 ),
(433,'ccc',60, 10 )
Query
SELECT T.id ,
T.name ,
T.col1 ,
T.col2 ,
SUM(T.col1) OVER( PARTITION BY T.id ORDER BY T.id ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
- SUM(T.col2) OVER ( PARTITION BY T.id ORDER BY T.id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) AS col3
FROM #TEST T;
Results
id | name | col1 | col2 | col3 |
---------------------------------
432 | xxx | 0 | 15 | 55 |
432 | yyy | 10 | 30 | 25 |
432 | zzz | 60 | 40 | -15 |
433 | aaa | 0 | 60 | 80 |
433 | bbb | 80 | 20 | 60 |
433 | ccc | 60 | 10 | 50 |
SQL Fiddle
This should work:
declare #total int = (select sum(col1) from Table)
select id, name, col1, col2, #total - (select sum(col2) from Table where date <= T.date) as col3, date from Table T
I was assuming you want to substract every time the previous total (based on the date). I hope this is OK.
You can use simple select query with cross apply
SELECT ID
,NAME
,COL1
,COL2
,A.C1 - (
SUM(COL2) OVER (
ORDER BY ID
)
) AS COL3
FROM TABLE1 T1
CROSS APPLY (
SELECT SUM(COL1) AS C1
FROM TABLE1 T2
) A
You can use two subqueries in SELECT fields list.
With the first you'll get a sum of all rows of your table named yourtable, in the second you'll get a sum of all rows before the current. So you can subtract two values.
Try this:
SELECT T.id, T.name, T.col1, T.col2,
ISNULL(
(SELECT SUM(T2.col1) FROM yourtable T2)
,0) -
ISNULL(
(SELECT SUM(T3.col2) FROM yourtable T3
WHERE T3.id <= T.id)
,0) as col3,
t.date
FROM yourtable T
Go on Sql fiddle example
EDIT
SELECT T.id, T.name, T.col1, T.col2,
ISNULL(
(SELECT SUM(T2.col1) FROM yourtable T2 where T2.id = T.id)
,0) -
ISNULL(
(SELECT SUM(T3.col2) FROM yourtable T3
WHERE T3.id = T.id AND T3.date <= T.date)
,0) as col3,
t.date
FROM yourtable T
Go on Sql Fiddle edited example
Pay attention: A deep edit can be a different question. Two queries are differents
Pay attention: it's no good a field named ID with repeated values

Update a table column with shuffled numbers within a range

I want to update a table column -Code- with shuffled numbers within its range, with no duplicates and without missing a number from the range.
for example the range is 1-9 and the following is the table:
Id|Name|Code
1 | AC | 2
2 | AB | 1
3 | CB | 5
4 | DE | 9
5 | FE | 3
6 | AE | 4
7 | FD | 6
8 | BD | 7
9 | DC | 8
I want result like in the above example. I am using SQL Server 2008.
Try this:
DECLARE #t TABLE ( ID INT, Code INT )
INSERT INTO #t
( ID )
VALUES ( 1 ),
( 2 ),
( 3 ),
( 4 ),
( 5 ),
( 6 ),
( 7 ),
( 8 ),
( 9 );
WITH cte
AS ( SELECT * ,
ROW_NUMBER() OVER ( ORDER BY NEWID() ) AS rn
FROM #t
)
UPDATE cte
SET code = rn
SELECT *
FROM #t
Output:
ID Code
1 2
2 7
3 4
4 1
5 6
6 8
7 5
8 9
9 3
If you want to manually set the range then you can set starting number of range and do something like:
DECLARE #start INT = 101
DECLARE #t TABLE ( ID INT, Code INT )
INSERT INTO #t
( ID )
VALUES ( 1 ),
( 2 ),
( 3 ),
( 4 ),
( 5 ),
( 6 ),
( 7 ),
( 8 ),
( 9 );
WITH cte
AS ( SELECT * ,
ROW_NUMBER() OVER ( ORDER BY NEWID() ) AS rn
FROM #t
)
UPDATE cte
SET code = rn + #start - 1
SELECT *
FROM #t
Output:
ID Code
1 104
2 108
3 107
4 105
5 102
6 103
7 106
8 101
9 109
NEWID() will give us a type of random id that you can use it for shuffling
As Giorgu Nakeuri answer you can use ROW_NUMBER() for a range of continuous and always start from 1
So I suggest you to use a query like this for shuffling a non-continues Range with different start point of 1:
;With t as (
SELECT *, ROW_NUMBER() OVER (ORDER BY NEWID()) As rndrn
FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY Id) As rn
FROM yourTable ) t1)
SELECT Id, Name, (SELECT ti.Id FROM t ti WHERE ti.rn = t.rndrn) As Code
FROM t
ORDER BY Id
Sample Result is:
ID Name Code
2 AB 2
3 CB 8
4 DE 7
5 FE 5
6 AE 6
7 FD 9
8 BD 3
9 DC 11
11 AC 4

TSQL UNION GETTING UNIQUE VALUE

I'm trying to get the unique record between two databases based on two criteria. The criteria is:
If the data is found in database 1 (#SCCM in my example below), it
is given preference
Grab the MAX resource id within the selected database
Here is an example, which is half working. The database preference is working, but the maximum resource id WITHIN that database isn't. Right now it's selecting the max between both #SMS and #SCCM
DECLARE #SMS TABLE (
name0 varchar(100),
resid int
)
DECLARE #SCCM TABLE (
name0 varchar(100),
resid int
)
INSERT INTO #SMS
SELECT 'TEST', 1000 UNION
SELECT 'TEST', 1500 UNION
SELECT 'TEST1', 2000 UNION
SELECT 'TEST2', 3000 UNION
SELECT 'TEST3', 4000
INSERT INTO #SCCM
SELECT 'TEST', 100 UNION
SELECT 'TEST', 150 UNION
SELECT 'TEST1', 200 UNION
SELECT 'TEST2', 300
SELECT MIN(SMSDB) as SMSDB, MAX(Resid), Name0 FROM
(
SELECT name0, resid, 2 as SMSDB FROM #SMS
UNION ALL
SELECT name0, resid, 1 as SMSDB FROM #SCCM
) as tbl
GROUP BY NAME0
Expected results:
SMSDB | Resid | Name0
----------------------
1 | 150 | TEST
1 | 200 | TEST1
1 | 300 | TEST2
2 | 4000 | TEST3
You can use partitions:
;WITH tbl as
(
SELECT name0, resid, 2 as SMSDB FROM SMS
UNION ALL
SELECT name0, resid, 1 as SMSDB FROM SCCM
),
t as (
SELECT *,
ROW_NUMBER()
over (partition By name0 order by SMSDB, resid desc )
as rn
FROM tbl
)
SELECT * FROM t
WHERE rn = 1
Results:
| NAME0 | RESID | SMSDB | RN |
------------------------------
| TEST | 150 | 1 | 1 |
| TEST1 | 200 | 1 | 1 |
| TEST2 | 300 | 1 | 1 |
| TEST3 | 4000 | 2 | 1
The partition solution may in fact be better, but it hurts my brain. What about just excluding the values in SMS if they exist in SCCM?
SELECT MIN(SMSDB) as SMSDB, MAX(Resid), Name0 FROM
(
SELECT name0, resid, 2 as SMSDB FROM #SMS SMS
WHERE NOT EXISTS (SELECT * FROM #SCCM WHERE name0 = SMS.name0)
UNION ALL
SELECT name0, resid, 1 as SMSDB FROM #SCCM
) as tbl
GROUP BY NAME0
or even
SELECT 1 as SMSDB, MAX(resid), name0 FROM #SCCM
GROUP BY name0
UNION ALL
SELECT 2 as SMSDB, MAX(resid), name0 FROM #SMS SMS
WHERE NOT EXISTS (SELECT * FROM #SCCM WHERE name0 = SMS.name0)
GROUP BY name0
ORDER BY name0

Resources