sqlserver running count - sql-server

Imagine the below table as A
col1 col2 col3 rank
1 2 n 5
1 2 n 6
2 3 a 3
While inserting below records from table B to table A, the rank column valus should be keep incrementing if the same records inserts.
Records in table B which gonna insert into A are
col1 col2 col3
1 2 n
2 3 a
The desired output in table A after the above records are inserted is,
col1 col2 col3 rank
1 2 n 5
1 2 n 6
1 2 n 7
2 3 a 3
2 3 a 4
Please help me how to acheive this.Thanks.

If the record in B are unique, then you could use a query like this
--------------EDIT-------------------
If B can have multiple records, you can use row_number() funcion with partition
insert into TestA
select b.*,
(select max([rank]) from TestA where col1 = b.col1 and col2 = b.col2 and col3 = b.col3)
+ row_number()over (partition by col1, col2, col3 order by col1, col2,col3 asc) as N
from TestB b
--------------END EDIT-------------------
Note: i renamed the table: TestA and TestB
insert into TestA
select b.*, (select max([rank])+1 from TestAwhere col1 = b.col1 and col2 = b.col2 and col3 = b.col3)
from TestB b
or with a JOIN like this
insert into testa
select b.*, mr+1 from TestB b
join
(select col1, col2, col3, max([rank]) as mr
from TestA A
group by col1, col2, col3) as M
on
b.col1 = M.col1 and b.col2 = M.col2 and b.col3 =M.col3

I would use an INSTEAD OF INSERT trigger for this. Like this:
CREATE TRIGGER rankInsertTrigger
ON A
INSTEAD OF INSERT
AS
BEGIN
INSERT INTO A(col1, col2, col3, rank)
SELECT i.col1, i.col2, i.col3,
MAX(SELECT a.rank
FROM A AS a
WHERE a.col1 = i.col1
AND a.col2 = i.col2
AND a.col3 = i.col3) + 1
FROM inserted i
END
Every time you now insert values into table A, this trigger runs and replaces the original insert with an insert that sets the rank you want.
For example, when you do INSERT INTO A(col1, col2, col3) VALUES (1, 2, n), what actually runs is the insert statement in the trigger (which takes the original values for col1, col2, col3 but overwrites rank).

Related

Get values NOT IN Table1 when join with Table2

I have two tables as below:
Table1:
Col1 Col2
834 2
834 3
834 5
877 1
877 2
877 5
900 10
900 2
900 3
Table2:
Col3
1
10
Expected Output:
Col1 Col3
834 1
834 10
877 10
900 1
This is what I have done so far:
select distinct t1.Col1,A.Col3
from Table1
cross apply
(select * from Table2 left join Table1 on Col2 = Col3) A
order by t1.Col1,A.Col3
I have been trying lot using join, cross apply and other sql function to get me the expected output. Any help is appreciated.
Logic:
I want to get the values of Col1 of Table1 for which Col3 does not matches with col2 of Table1.
For Eg: Values 1 and 10 of Col3 of table2 is not there for value 834 of col1 of table1. Hence there are two rows for 834, one with value 1 and other with 10.
Please try with the below code snippet.
DECLARE #Table1 TABLE(
Col1 INT NOT NULL,
Col2 INT NOT NULL
);
INSERT INTO #Table1 VALUES(834 , 2)
INSERT INTO #Table1 VALUES(834 , 3)
INSERT INTO #Table1 VALUES(834 , 5)
INSERT INTO #Table1 VALUES(877 , 1)
INSERT INTO #Table1 VALUES(877 , 2)
INSERT INTO #Table1 VALUES(877 , 5)
INSERT INTO #Table1 VALUES(900 , 10)
INSERT INTO #Table1 VALUES(900 , 2)
INSERT INTO #Table1 VALUES(900 , 3)
DECLARE #Table2 TABLE(
Col3 INT NOT NULL
);
INSERT INTO #Table2 VALUES(1)
INSERT INTO #Table2 VALUES(10)
SELECT a.Col1,a.Col3 FROM (SELECT DISTINCT a.Col1,b.Col3 FROM #Table1 a,#Table2 b
WHERE a.Col2 <> b.Col3) a
LEFT JOIN #Table1 c on a.Col1 = c.Col1 and a.Col3 = c.Col2
WHERE c.Col1 is null
I doubt you need any join in here. All you want to select from table1 are the rows with matching value in table2. Something like this :
Select distinct col1, col2 from table1
Where col2 not in (select col3 from table2)
select a.col1, a.col2
from Table1 a
where not exists(select * from Table2 b where a.col1 = b.col3)
This may work...

How to join more than two tables using sql without Common Columns

Example:
Table 1:
Col1 Col2
----------- -------------
A 1
B 2
D 3
E 4
Table 2:
Col3 Col4
----------- -------------
A 7
E 9
Z 5
Table 3:
Col5 Col6
----------- -------------
Y 8
Expected output:
Col1 Col2 Col3 Col4 Col5 Col6
---- ---- ---- ---- ---- ----
A 1 A 7 Y 8
B 2 E 9 NULL NULL
D 3 Z 5 NULL NULL
E 4 NULL NULL NULL NULL
I want the output as shown in the picture.
If there are three tables with columns as Col11, Col2 and Col3, Col4 and Col5 and Col6
then expected output should be as Col1, Col2, Col3, Col4, Col5, Col6 without any joins. It should just Table2 is at right hand side of the Table1 And Table3 should be at right of the Table2. If number of rows don't match then Null values will consume the space.
I know the solution for Two tables. But Need SQL query syntax for n number of tables.
-Thanks in Advance.
Although I can't quite see why you'd want to do this, I've attempted to answer the question as an exercise for my own learning!
Thanks to #user2864740 for the idea of using ROW_NUMBER to synthesize a common value between each table!
Here's the query:
SELECT
col1,
col2,
col3,
col4,
col5,
col6
FROM
(SELECT ROW_NUMBER() OVER(ORDER BY col1) AS Row,
col1, col2
FROM table1) T1
FULL OUTER JOIN
(SELECT ROW_NUMBER() OVER(ORDER BY col3) AS Row,
col3, col4
FROM table2) T2 ON T1.Row = T2.Row
FULL OUTER JOIN
(SELECT ROW_NUMBER() OVER(ORDER BY col5) AS Row,
col5, col6
FROM table3) T3 ON T1.Row = T3.Row
And a SQL Fiddle demonstrating it: http://sqlfiddle.com/#!3/6c2db/6
When you are joining for no reason you must "make something up" in this case use row_number and join on that. Notice this would cut off table2 and table3 results if they had more than table 1, to avoid that change left joins to full outer joins and Cartesian everything. Simplest way to do this is :
Select Col1, Col2, Col3, Col4, Col5, Col6
From
(select Col1, Col2, ROW_NUMBER() Over (order by Col1,Col2) 'Rnk1'
From table1 ) t1
left join
(select Col3, Col4, ROW_NUMBER() Over (order by Col3,Col4) 'Rnk2'
From table1 ) t2
On t1.rnk1 = t2.rnk2
left join
(select Col5, Col6, ROW_NUMBER() Over (order by Col5,Col6) 'Rnk3'
From table3 ) t3
On t1.rnk1 = t3.rnk3

Trigger on insert from table 1 to insert row into table 2 if the data is unique, update if it's not

I need to make a trigger that, upon an insert into table1, checks if the same values from 3 columns in table2 match, if not it inserts that row into table2. If there is a match it then updates the row that matches. Here's what I've gathered so far, but it doesn't do the IF EXISTS check I need it to. I'm not certain how exactly to structure it in this case due to never having worked with triggers.
CREATE TRIGGER Trigger_Name on Table_Name
FOR INSERT
AS
BEGIN
INSERT INTO
TABLE 2
(
Col1,
Col2,
Col3,
Col4
)
SELECT
(
Col1,
Col2,
Col3,
Col4
)
FROM
INSERTED
GO
The IF EXISTS criteria need to see if table1.col1=table2.col1, table1.col2=table2.col2, table1.col3,table2.col3
Using SQL server 2008. Any help is much appreciated
UPDATE table2
SET col1 = inserted.col1
, col2 = inserted.col2
, col3 = inserted.col3
, col4 = inserted.col4
FROM table2
INNER
JOIN inserted
ON inserted.col1 = table2.col1
AND inserted.col2 = table2.col2
AND inserted.col3 = table2.col3
;
INSERT INTO table2 (col1, col2, col3, col4)
SELECT col1
, col2
, col3
, col4
FROM inserted
WHERE NOT EXISTS (
SELECT *
FROM table1
WHERE col1 = inserted.col1
AND col2 = inserted.col2
AND col3 = inserted.col3
)
;

how to sum conditionally?

I have a following table
Col1 Col2 Col3
A1 1 null
A1 2 null
B1 5 null
B2 6 null
M1 1 M
M2 2 M
M3 3 M
J1 1 J
J2 2 J
I want to sum Col2 based on Col1. The query will be like following,
select Col1, sum (Col2)
group by Col1
However, if Col3 has the same letter, I want sum up Col2 for all Col1. So the result table should be like
Col1 Col2
A1 3
B1 5
B2 6
M1 6
M2 6
M3 6
J1 3
J2 3
How do I change my query to get above table?
Edit after comment / update to question. I didn't know a clever way, seems like some others have one though.
select * from (
select Col1, SUM(Col2) Col2
from Table
where Col3 is null
group by Col1
union
select mainset.Col1, tmp.Col2
from Table mainset
join
(
select Col3, SUM(Col2) Col2
from Table
where Col3 is not null
group by Col3
) tmp on tmp.Col3 = mainset.Col3
where mainset.Col3 is not null
) fullset
order by fullset.Col1
You could do something like this (I named the table #a):
;WITH col3Sum AS
(
SELECT Col3, SUM(Col2) SUM3
FROM #a
WHERE col3 IS NOT NULL
GROUP BY col3
),
col1Sum AS
(
SELECT Col1, SUM(Col2) sum1
FROM #a
GROUP BY Col1
)
SELECT c1.Col1, ISNULL(c3.SUM3, c1.sum1) AS Col2
FROM col1Sum c1
LEFT JOIN col3Sum c3
ON c1.Col1 LIKE c3.Col3+'%'
ORDER BY c1.Col1

Is there a T-SQL shortcut for getting the max values of two columns

What I mean is, say you have a table like:
Col1 Col2
---- ----
1 1
1 9
2 1
2 3
4 1
4 2
I want to get: Col1=4 and Col2=2, because Col1 has precendence. In other words, I want the largest value of Col1 and for that value the largest value of Col2 in a minimal T-SQL expression. It's almost like saying:
SELECT TOP 1 Col1, Col2
FROM MyTable
ORDER BY Col1, Col2 DESC
But doing this in such a way that the Col1, Col2 values are usable within another query.
Not really anything like MAX(Col1, Col2). If you wanted to simulate MAX ... GROUP BY X you could use
WITH T AS
(
SELECT Col1,
Col2,
ROW_NUMBER () OVER (PARTITION BY X ORDER BY Col1 DESC, Col2 DESC) AS RN
FROM MyTable
)
SELECT Col1,
Col2,
X
FROM T
WHERE RN= 1;
Like this? One row
SELECT ...
FROM
SOmeTable
JOIN
(
SELECT TOP 1 Col1, Col2
FROM MyTable
ORDER BY Col1, Col2 DESC
) foo ON S.Col1 = foo.Col1
Or per outer row?
SELECT ...
FROM
SOmeTable S
CROSS APPLY
(
SELECT TOP 1 Col2
FROM MyTable M
WHERE S.somecol = M.SomeCol
ORDER BY Col2 DESC
) foo
SELECT ...
FROM
SOmeTable S
CROSS APPLY
(
SELECT Col1, MAX(Col2) AS MaxCOl2
FROM MyTable M
GROUP BY Col1
) foo ON S.Col1 = foo.Col1
WITH t(Col1,maxCol1,maxCol2) AS (
SELECT
Col1,
MAX(Col1) OVER(),
MAX(Col2) OVER(PARTITION BY Col1)
)
SELECT TOP 1 maxCo11,maxCol2 FROM t WHERE Col1 = maxCol1

Resources