Select invoices based on quantity needed - sql

I have a table that looks like this:
+---------------+---------------+------------------+--------------+
| InvoiceNumber | ProductNumber | ReceivedQuantity | ReceivedDate |
+---------------+---------------+------------------+--------------+
| INV001 | P001 | 500 | 09/01/2015 |
| INV002 | P001 | 600 | 09/02/2015 |
| INV003 | P001 | 700 | 09/03/2015 |
+---------------+---------------+------------------+--------------+
When a product is ordered. System needs to know which invoice it gets it from. First in first out.
For example I need 1000 quantity of product number P001. It should select the following invoices. It does not display the last invoice since 500 + 600 is already sufficient quantity
+---------------+---------------+------------------+--------------+
| InvoiceNumber | ProductNumber | ReceivedQuantity | ReceivedDate |
+---------------+---------------+------------------+--------------+
| INV001 | P001 | 500 | 09/01/2015 |
| INV002 | P001 | 600 | 09/02/2015 |
+---------------+---------------+------------------+--------------+
I can replicate this by making a cursor and looping through the table but looking for the best way to achieve this. Any nudge to the right direction would help a lot.

I think you can use a query like this:
;WITH t As (
SELECT *
, ROW_NUMBER() OVER (ORDER BY ReceivedDate, InvoiceNumber) As RowNo
FROM yourTable
), firstOverflow AS (
SELECT TOP(1)
t1.RowNo
FROM t t1
LEFT JOIN
t t2 ON t1.ProductNumber = t2.ProductNumber AND t1.ReceivedDate >= t2.ReceivedDate
GROUP BY t1.RowNo, t1.InvoiceNumber, t1.ProductNumber, t1.ReceivedQuantity, t1.ReceivedDate
HAVING SUM(t2.ReceivedQuantity) >= 1000
ORDER BY SUM(t2.ReceivedQuantity) - 1000)
SELECT *
FROM t
JOIN
firstOverflow ON t.RowNo <= firstOverflow.RowNo;
A better solution is this:
DECLARE #value int = 1000;
WITH t As (
SELECT *
, ROW_NUMBER() OVER (ORDER BY ReceivedDate, InvoiceNumber) As seq
FROM yourTable
), s As (
SELECT t.InvoiceNumber, t.ProductNumber, t.ReceivedQuantity, t.ReceivedDate, SUM(tt.ReceivedQuantity) As currentTotal
FROM t
LEFT JOIN
t tt ON t.ProductNumber = tt.ProductNumber AND t.seq >= tt.seq
GROUP BY t.InvoiceNumber, t.ProductNumber, t.ReceivedQuantity, t.ReceivedDate
), st As (
SELECT *
, ROW_NUMBER() OVER (ORDER BY (CASE WHEN s.currentTotal > #value THEN -currentTotal ELSE Null END) DESC) As seq
FROM s)
SELECT st.InvoiceNumber, st.ProductNumber, st.ReceivedQuantity, st.ReceivedDate
FROM st
WHERE currentTotal < #value
UNION ALL
SELECT st.InvoiceNumber, st.ProductNumber, st.ReceivedQuantity, st.ReceivedDate
FROM st
WHERE currentTotal >= #value AND st.seq = 1;

Try this query and give some feedback:
DECLARE #table TABLE (InvoiceNumber nvarchar(100),
ProductNumber nvarchar(100),
ReceivedQuantity int)
INSERT INTO #table VALUES ('inv001', 'p001', 500)
INSERT INTO #table VALUES ('inv002', 'p001', 600)
INSERT INTO #table VALUES ('inv003', 'p001', 600)
INSERT INTO #table VALUES ('inv004', 'p001', 600)
SQL 2012:
SELECT v.* FROM
(
SELECT t.*,
SUM(ReceivedQuantity) OVER (PARTITION BY ProductNumber ORDER BY InvoiceNumber) AS sum
FROM #table t
) v
WHERE sum <= 1000
SQL 2008:
SELECT v.* FROM
(
SELECT
a.InvoiceNumber
, a.ProductNumber
, SUM(b.ReceivedQuantity) AS sum
FROM
#table a
INNER JOIN #table b
ON a.InvoiceNumber >= b.InvoiceNumber AND a.ProductNumber = b.ProductNumber
GROUP BY
a.InvoiceNumber
, a.ProductNumber
) v
WHERE sum <= 1000

Related

Find nearest SUM amount from table SQL SERVER

Query
Declare #table1 TABLE (accountno varchar(max), saved_amount decimal)
INSERT INTO #table1 VALUES
('001',25),
('002',5)
Declare #table2 TABLE (accountno varchar(max), payamount decimal,ilno int)
INSERT INTO #table2 VALUES
('001',10,1),
('001',10,2),
('001',10,3),
('001',10,4),
('002',10,1),
('002',10,2);
WITH aa
AS (
SELECT a.*
,b.ilno
,b.payamount
,SUM(payamount) OVER (
PARTITION BY a.accountno ORDER BY CAST(a.accountno AS INT)
,ilno
) AS total_amount
FROM #table1 a
LEFT JOIN #table2 b ON a.accountno = b.accountno
)
,bb
AS (
SELECT accountno
,MAX(ilno) AS ilno
FROM aa
WHERE saved_amount >= total_amount
GROUP BY accountno
)
SELECT a.* FROM aa a INNER JOIN bb b on a.accountno =b.accountno AND a.ilno = b.ilno
Result
accountno | saved_amount | ilno | payamount | total_amount
----------------------------------------------------------
001 | 25 | 2 | 10 | 20
Expected Result
accountno | saved_amount | ilno | payamount | total_amount
----------------------------------------------------------
001 | 25 | 2 | 10 | 20
002 | 5 | 1 | 10 | 10
What I want is
If saved_amount is less than the first ilno, then get the first ilno else
get the highest ilno where saved_amount>=total_amount
You have a running total that you compare with the saved amount. You want the highest running total that doesn't exceed the saved amount. But in case even the initial pay amount exceeds the saved amount already, you want to default to this record. So the main task is to find a way of ranking the records. In my query I do it like this:
Prefer records where the running total does not exceed the saved amount.
Then look at the abolute of their difference and take the smallest.
There are certainly other ways that achieve the same. Maybe even methods that you find more readable. Then just adjust the order by clause in the ranking query.
with summed as
(
select
t1.*,
from #table1 t1
join
(
select
ilno,
payamount,
sum(payamount) over (partition by accountno order by ilno) as total_amount
from #table2
) on t2.accountno = t1.accountno
)
, ranked as
(
select summed.*,
row_number() over (partition by accountno
order by case when saved_amount >= total_amount then 1 else 2 end,
abs(saved_amount - total_amount)
) as rn
)
select *
from ranked
where rn = 1;
This is not the "nearest sum", as you said in the title, but the one that obeys the specified rules. So with a saved amount of 100 and paid amounts of first 1 and then 100, you'd get the record with a total of 1 (which is 99 less than the saved amount) and not the one with a total of 101 (which is only 1 more than the saved amount).
Other way to solve using flags:
first calculated one flag to point if saved_amount >= payamount for current row
calculated three more flags:
group_flag to show is there a case where saved_amount >= payamount for the given accountno
[min_ilno] and [max_ilno] for given account
Having this flags, the final result set is calculated easily. Here is the code:
WITH DataSource AS
(
SELECT a.*
,b.ilno
,b.payamount
,SUM(payamount) OVER (PARTITION BY a.accountno ORDER BY ilno) AS total_amount
,IIF(a.saved_amount >= SUM(payamount) OVER (PARTITION BY a.accountno ORDER BY ilno), 1, 0) AS [flag]
FROM #table1 a
LEFT JOIN #table2 b
ON a.accountno = b.accountno
),
DataSourceFinal AS
(
SELECT *
,MAX(flag) OVER (PARTITION BY accountno) as [group_flag]
,MIN(IIF(flag = 0 ,ilno, NULL)) OVER (PARTITION BY accountno) as [min_ilno]
,MAX(IIF(flag = 1 ,ilno, NULL)) OVER (PARTITION BY accountno) as [max_ilno]
FROM DataSource
)
SELECT accountno, saved_amount, ilno, payamount, total_amount
FROM DataSourceFinal
WHERE ([group_flag] = 1 AND [ilno] = [max_ilno])
OR ([group_flag] = 0 AND [ilno] = [min_ilno]);
and the output:

display 3 or more consecutive rows(Sql)

I have a table with below data
+------+------------+-----------+
| id | date1 | people |
+------+------------+-----------+
| 1 | 2017-01-01 | 10 |
| 2 | 2017-01-02 | 109 |
| 3 | 2017-01-03 | 150 |
| 4 | 2017-01-04 | 99 |
| 5 | 2017-01-05 | 145 |
| 6 | 2017-01-06 | 1455 |
| 7 | 2017-01-07 | 199 |
| 8 | 2017-01-08 | 188 |
+------+------------+-----------+
now what i am trying to do is to display 3 consecutive rows where people were >=100 like this
+------+------------+-----------+
| id | date1 | people |
+------+------------+-----------+
| 5 | 2017-01-05 | 145 |
| 6 | 2017-01-06 | 1455 |
| 7 | 2017-01-07 | 199 |
| 8 | 2017-01-08 | 188 |
+------+------------+-----------+
can anyone help me how to do this query using oracle database. I am able to display rows which are above 100 but not in a consecutive way
Table creation(reducing typing time for people who will be helping)
CREATE TABLE stadium
( id int
, date1 date, people int
);
Insert into stadium values (
1,TO_DATE('2017-01-01','YYYY-MM-DD'),10);
Insert into stadium values
(2,TO_DATE('2017-01-02','YYYY-MM-DD'),109);
Insert into stadium values(
3,TO_DATE('2017-01-03','YYYY-MM-DD'),150);
Insert into stadium values(
4,TO_DATE('2017-01-04','YYYY-MM-DD'),99);
Insert into stadium values(
5,TO_DATE('2017-01-05','YYYY-MM-DD'),145);
Insert into stadium values(
6,TO_DATE('2017-01-06','YYYY-MM-DD'),1455);
Insert into stadium values
(7,TO_DATE('2017-01-07','YYYY-MM-DD'),199);
Insert into stadium values(
8,TO_DATE('2017-01-08','YYYY-MM-DD'),188);
Thanks in advance for the help
Assuming you mean >= 100, there are a couple of ways. One method just uses lead() and lag(). But a simple method defines each group >= 100 by the number of values < 100 before it. Then it uses count(*) to find the size of the consecutive values:
select s.*
from (select s.*, count(*) over (partition by grp) as num100pl
from (select s.*,
sum(case when people < 100 then 1 else 0 end) over (order by date) as grp
from stadium s
) s
) s
where num100pl >= 3;
Here is a SQL Fiddle showing that the syntax works.
You can use the following sql script to get the desired output.
WITH partitioned AS (
SELECT *, id - ROW_NUMBER() OVER (ORDER BY id) AS grp
FROM stadium
WHERE people >= 100
),
counted AS (
SELECT *, COUNT(*) OVER (PARTITION BY grp) AS cnt
FROM partitioned
)
select id , visit_date,people
from counted
where cnt>=3
I'm assuming that both the id and date columns are sequential and correspond to each other (there will need to be additional ROW_NUMBER() if the ids are not sequential with the dates, and more complex logic included if the dates are not necessarily sequential).
SELECT
*
FROM
(
SELECT
*
,COUNT(date) OVER (PARTITION BY sequential_group_num) AS num_days_in_sequence
FROM
(
SELECT
*
,(id - ROW_NUMBER() OVER (ORDER BY date)) AS sequential_group_num
FROM
stadium
WHERE
people >= 100
) AS subquery1
) AS subquery2
WHERE
num_days_in_sequence >= 3
That produces the following output:
id date people sequential_group_num num_days_in_sequence
----------- ---------- ----------- -------------------- --------------------
5 2017-01-05 145 2 4
6 2017-01-06 1455 2 4
7 2017-01-07 199 2 4
8 2017-01-08 188 2 4
By using joins we can display the consecutive rows like this
SELECT id, date1, people FROM stadium a WHERE people >= 100
AND (SELECT people FROM stadium b WHERE b.id = a.id + 1) >= 100
AND (SELECT people FROM stadium c WHERE c.id = a.id + 2) >= 100
OR people >= 100
AND (SELECT people FROM stadium e WHERE e.id = a.id - 1) >= 100
AND (SELECT people FROM stadium f WHERE f.id = a.id + 1) >= 100
OR people >= 100
AND (SELECT people FROM stadium g WHERE g.id = a.id - 1) >= 100
AND (SELECT people FROM stadium h WHERE h.id = a.id - 2) >= 100
order by id;
select distinct
t1.*
from
stadium t1
join
stadium t2
join
stadium t3
where
t1.people >= 100
and t2.people >= 100
and t3.people >= 100
and
(
(t1.id + 1 = t2.id
and t2.id + 1 = t3.id)
or
(
t2.id + 1 = t1.id
and t1.id + 1 = t3.id
)
or
(
t2.id + 1 = t3.id
and t3.id + 1 = t1.id
)
)
order by
id;
SQL script:
SELECT DISTINCT SS.*
FROM STADIUM SS
INNER JOIN
(SELECT S1.ID
FROM STADIUM S1
WHERE 3 = (
SELECT COUNT(1)
FROM STADIUM S2
WHERE (S2.ID=S1.ID OR S2.ID=S1.ID+1 OR S2.ID=S1.ID+2)
AND S2.PEOPLE >= 100
)) AS SS2
ON SS.ID>=SS2.ID AND SS.ID<SS2.ID+3
select *
from(
select * , count(*) over (partition by grp) as total
from
(select * , Sum(case when people < 100 then 1 else 0 end) over (order by date) as grp
from stadium) T -- inner Query 1
where people >=100 )S--inner query 2
where total >=3 --outer query
I wrote the following solution for this similar leetcode problem:
with groupVisitsOver100 as (
select *,
sum(
case
when people < 100 then 1
else 0
end
) over (order by date1) as visitGroups
from stadium
),
filterUnder100 as (
select
*
from groupVisitsOver100
where people >= 100
),
countGroupsSize as (
select
*,
count(*) over (partition by visitGroups) as groupsSize
from filterUnder100
)
select id, date1, people from countGroupsSize where groupsSize >= 3 order by date1

How to calculate average in SQL?

lets say I have the following table:
**FOOD** | **AMOUNT**
Bread | 2
Banana | 5
Pizza | 4
Apple | 57
Mandarin| 9
Orange | 8
Final result:
Bread | Percentage Of Total
Banana | percentage of total
etc
etc
I tried it in every single way, but couldn't find a solution. I hope someone can help me.
Using ANSI SQL (and SQL Server supports this syntax), you can do:
select food, sum(amount),
sum(amount) / sum(sum(amount)) over () as proportion_of_total
from t
group by food;
Note: Some databases do integer division, so you may need to convert to a floating point or fixed point type.
We can also try like below-
DECLARE #tbl AS TABLE
(
food VARCHAR(15)
,amount INT
)
INSERT INTO #tbl VALUES
('bread', 2)
,('banana', 5)
,('pizza', 4)
,('apple', 57)
,('mandarin', 9)
,('orange', 8)
SELECT
DISTINCT
food
,SUM(amount) OVER() TotalAmount
,SUM(amount) OVER (PARTITION BY food) PerFoodTotal
,CAST(SUM(amount) OVER (PARTITION BY food) * 100. / (SUM(amount) OVER()) AS DECIMAL(10,2)) [Percentage Of Total]
FROM #tbl
OUTPUT
food TotalAmount PerFoodTotal Percentage Of Total
--------------- ----------- ------------ ---------------------------------------
apple 85 57 67.06
banana 85 5 5.88
bread 85 2 2.35
mandarin 85 9 10.59
orange 85 8 9.41
pizza 85 4 4.71
(6 row(s) affected)
You can try something like this:
declare #tbl as table (
food varchar(15)
,amount int
)
insert into #tbl values
('bread', 2)
,('banana', 5)
,('pizza', 4)
,('apple', 57)
,('mandarin', 9)
,('orange', 8)
select SUM(amount) from #tbl
select
food
,SUM(amount) as [food amount]
,(SUM(cast(amount as numeric(18,2))) / (select sum(cast(amount as numeric(18,2))) from #tbl)) * 100 as [Percentage Of Total]
,(select sum(amount) from #tbl) as total
from #tbl
group by food
Here you got a way fo getting the PercentageOfTotal, asuming that the sum of all will not be 0
DECLARE #total INT = (SELECT SUM(AMOUNT) FROM Table1)
SELECT FOOD, CAST((CAST((100 * AMOUNT) AS DECIMAL (18,2)) / #total ) AS DECIMAL(18,2)) AS PercentageOfTotal from Table1
SQL Fiddle
MS SQL Server 2014 Schema Setup:
CREATE TABLE MusicGenres (name varchar(10)) ;
INSERT INTO MusicGenres (name)
VALUES ('Pop'),('Techno'),('Trance'),('trap'),('Hardcore'),('Electro') ;
CREATE TABLE Table2 (SongID int, MusicGenres varchar(10)) ;
INSERT INTO Table2 (SongID, MusicGenres)
VALUES (1,'Hardcore')
,(2,'Hardcore')
,(3,'Pop')
,(4,'Trap')
,(5,'Hardcore')
,(6,'Pop')
,(7,'Electro')
,(8,'Electro')
,(9,'Pop')
,(10,'Pop')
,(11,'Pop')
;
Query 1:
SELECT s1.name
, s1.recCount
, ( s1.recCount / CAST( ( SUM(recCount) OVER() ) AS decimal(5,2) ) )*100 AS pct
FROM (
SELECT m.name
, count(t.SongID) AS recCount
FROM MusicGenres m
LEFT OUTER JOIN Table2 t ON m.name = t.MusicGenres
GROUP BY m.name
) s1
Could be shortened to
SELECT m.name
, count(t.SongID) AS recCount
, ( count(t.SongID) / CAST( ( SUM(count(t.SongID)) OVER() ) AS decimal(5,2) )
)*100 AS pct
FROM MusicGenres m
LEFT OUTER JOIN Table2 t ON m.name = t.MusicGenres
GROUP BY m.name
Results:
| name | recCount | pct |
|----------|----------|---------|
| Electro | 2 | 18.1818 |
| Hardcore | 3 | 27.2727 |
| Pop | 5 | 45.4545 |
| Techno | 0 | 0 |
| Trance | 0 | 0 |
| trap | 1 | 9.0909 |

Selecting records with maximum value in group

I have a transaction table with the following structure:
select t.[GUID], t.[ID], ts.Description "Status", t.Payee, t.Amount, t.SequenceNumber
from [Transaction] t
inner join TransactionStatus ts on t.StatusID = ts.ID
GUID | ID | Status | Payee | Amount | SequenceNumber
AF732CF5-E6C0-E411-B8F6-004056AB77C2 | 1 | Posted | Amy | 500.00 | 1
AF732CF5-E6C0-E411-B8F6-004056AB77C2 | 2 | Voided | Amy | 500.00 | 2
1F7D880C-E7C0-E411-B8F6-004056AB77C2 | 3 | Posted | Bob | 70.00 | 1
AF732CF5-E6C0-E411-B8F6-004056AB77C2 | 4 | Posted | Amy | 512.50 | 3
1F7D880C-E7C0-E411-B8F6-004056AB77C2 | 5 | Posted | Bob | 66.00 | 2
F2CC0B03-76C7-E411-A48D-004056AB787C | 6 | Pending | Carol | 240.00 | NULL
I'm trying to construct a query to group the records by GUID and select the single record with the largest SequenceNumber (if it isn't NULL):
GUID | ID | Status | Payee | Amount | SequenceNumber
AF732CF5-E6C0-E411-B8F6-004056AB77C2 | 4 | Posted | Amy | 512.50 | 3
1F7D880C-E7C0-E411-B8F6-004056AB77C2 | 5 | Posted | Bob | 66.00 | 2
F2CC0B03-76C7-E411-A48D-004056AB787C | 6 | Pending | Carol | 240.00 | NULL
I've tried adding this line:
where SequenceNumber = (select MAX(SequenceNumber) from [Transaction] t2 where t.[GUID] = t2.[GUID])
but that doesn't get me any transactions where the status is Pending (they don't have sequence numbers). How can I fix this query?
If it's SQL-Server you can use a CTE + ROW_NUMBER:
WITH CTE AS
(
select t.[GUID], t.[ID], ts.Description "Status", t.Payee, t.Amount, t.SequenceNumber,
rn = row_number() over (partition by t.[GUID] Order By t.SequenceNumber DESC)
from [Transaction] t
inner join TransactionStatus ts on t.StatusID = ts.ID
)
SELECT GUID, ID, Status, Payee, Amount, SequenceNumber
FROM CTE
WHERE rn = 1
This will include the row where SequenceNumber is null. If you want all rows with the maximum SequenceNumber(in case of ties) use DENSE_RANK instead of ROW_NUMBER.
You can calculate the MAX(ID) and it's related [GUID] in a subquery and JOIN to it in order to get the desired results:
Sample subquery:
SELECT [GUID] ,
MAX(ID) MaxId
FROM Transaction
GROUP BY [GUID]
Would produce:
GUID MaxId
1F7D880C-E7C0-E411-B8F6-004056AB77C2 5
AF732CF5-E6C0-E411-B8F6-004056AB77C2 4
F2CC0B03-76C7-E411-A48D-004056AB787C 6
Full Demo:
CREATE TABLE #Transaction
(
[GUID] VARCHAR(36) ,
[ID] INT ,
[Status] VARCHAR(7) ,
[Payee] VARCHAR(5) ,
[Amount] INT ,
[SequenceNumber] VARCHAR(4)
);
INSERT INTO #Transaction
( [GUID], [ID], [Status], [Payee], [Amount], [SequenceNumber] )
VALUES ( 'AF732CF5-E6C0-E411-B8F6-004056AB77C2', 1, 'Posted', 'Amy', 500.00,
'1' ),
( 'AF732CF5-E6C0-E411-B8F6-004056AB77C2', 2, 'Voided', 'Amy', 500.00,
'2' ),
( '1F7D880C-E7C0-E411-B8F6-004056AB77C2', 3, 'Posted', 'Bob', 70.00,
'1' ),
( 'AF732CF5-E6C0-E411-B8F6-004056AB77C2', 4, 'Posted', 'Amy', 512.50,
'3' ),
( '1F7D880C-E7C0-E411-B8F6-004056AB77C2', 5, 'Posted', 'Bob', 66.00,
'2' ),
( 'F2CC0B03-76C7-E411-A48D-004056AB787C', 6, 'Pending', 'Carol',
240.00, NULL );
SELECT #Transaction.*
FROM #Transaction
INNER JOIN ( SELECT [GUID] ,
MAX(ID) MaxId
FROM #Transaction
GROUP BY [GUID]
) t ON t.[GUID] = #Transaction.[GUID]
AND t.MaxId = #Transaction.ID
ORDER BY ID
Try this way to get maximum SequenceNumber
CASE WHEN MAX(SequenceNumber IS NULL) = 0 THEN MAX(SequenceNumber) ELSE NULL END AS SequenceNumber
I don't know if SQL Server has windowing functions, so you may be able to do this more cleanly, but here's a vanilla SQL solution:
select highest.[GUID],
highest.[ID],
ts.Description "Status",
highest.Payee,
highest.Amount,
highest.SequenceNumber
from [Transaction] highest
join TransactionStatus ts
on ts.ID = highest.ID
left join [Transaction] higher
on higher.[GUID] = highest.[GUID]
and higher.SequenceNumber > highest.SequenceNumber
where higher.[GUID] is null;
omething like this:
SELECT * FROM
(
select
t.[GUID], t.[ID], ts.Description "Status", t.Payee, t.Amount,
ROW_NUMBER() OVER PARTITION BY (t.[GUID]
ORDER BY t.SequenceNumber DESC) AS rownum
from [Transaction] t
inner join TransactionStatus ts on t.StatusID = ts.ID
)vals where vals.rownum = 1

Find and delete duplicate friend connections in SQL Server

I need a script to find Member who has a friend connection more than once so it doesn't show their friendship more than once on the website.
The MemberConnection table is as follows:
+----------------------+------------+----------------+
| MemberConnectionID | MemberID | ConnMemberID |
+----------------------+------------+----------------+
| 25 | 33 | 43 |
| 26 | 43 | 33 |
| 27 | 13 | 143 |
| 28 | 143 | 13 |
| 29 | 33 | 43 |
+----------------------+------------+----------------+
As you can see rows 25 and 29 are identical and I need to find these duplicates so they can be deleted.
How can I write a script for this?
Any help that anyone can provide would be greatly appreciated.
Many thanks in advance
neojakey
Try this if you want to leave one connection:
Use this to select connections:
;WITH CTE
AS
(
SELECT
MemberConnectionID,
ROW_NUMBER() OVER (PARTITION BY MemberID, ConnMemberID ORDER BY MemberConnectionID) RN
FROM MemberConnection
)
SELECT
MemberConnectionID
FROM CTE
WHERE RN > 1
or use this to delete from table:
;WITH CTE
AS
(
SELECT
ROW_NUMBER() OVER (PARTITION BY MemberID, ConnMemberID ORDER BY MemberConnectionID) RN
FROM MemberConnection
)
DELETE
FROM CTE
WHERE RN > 1
You can do something like :
SELECT * FROM
(SELECT MemberID,ConnMemberID ,count( MemberID,ConnMemberID ) as c FROM MemberConnection group by MemberID,ConnMemberID ) x
WHERE x.c >1
This will show you all repeated rows.
Using this as a test:
DECLARE #Table AS TABLE
(
MemberConnectionID INT ,
MemberID INT ,
ConMemberID INT
)
INSERT INTO #Table
SELECT 1 ,
2 ,
3
INSERT INTO #Table
SELECT 2 ,
3 ,
4
INSERT INTO #Table
SELECT 3 ,
2 ,
3
Select occurence of member connections
SELECT COUNT(MemberConnectionID) AS Occurence ,
MemberID ,
ConMemberID
FROM #Table
GROUP BY MemberID ,
ConMemberID
Delete Statement
DELETE FROM #Table
FROM #Table t
INNER JOIN ( SELECT MemberID ,
ConMemberID
FROM ( SELECT COUNT(MemberConnectionID) AS Occurence ,
MemberID ,
ConMemberID
FROM #Table
GROUP BY MemberID ,
ConMemberID
) t2
WHERE t2.Occurence > 1
) t3 ON t3.MemberID = T.MemberID
AND t3.ConMemberID = t.ConMemberID
I always use this little query (changed to meet your table).
Delete MemberConnection
from MemberConnection
join
(select max(MemberConnectionId)as CountIt, MemberId, ConnMemberId
from #MemberConnection
group by MemberId, ConnMemberId
having count(1) > 1
) as derived
on MemberConnection.MemberId = derived.MemberId
and MemberConnection.ConnMemberId = derived.ConnMemberId
and CountIt > MemberConnectionId