Retrieve rows on the basis of repeating value of a column - sql

I want to retrieve data from my table Card.
table Card(
MembershipNumber,
EmbossLine,
status,
EmbossName
)
Such that only those rows should be returned that have repeating MembershipNumber i.e having count greater than 1.
Like if I Have following records
(11,0321,'active','John')
(11,0322,'active','John')
(23,0350,'active','Mary')
(46,0383,'active','Fudge')
(46,0382,'active','Fudge')
(46,0381,'active','Fudge')
The query should return all records except the third one. Is it possible?
EDITED I got the answer for my question. I have another query. I want to filter the rows by status too but when I run the following query I dont get the desired result:
SELECT EmbossLine,Membershipnumber,status,embossname,*
FROM (SELECT *,
Count(MembershipNumber)OVER(partition BY EmbossName) AS cnt
FROM card) A
WHERE cnt > 1 AND status='E0'
Before Adding status in the where clause, it works perfectly fine. see Picture
After adding filtering by status

Use Count() Over() window function to do this.
SELECT *
FROM (SELECT *,
Count(MembershipNumber)OVER(partition BY EmbossName) AS cnt
FROM youurtable) A
WHERE cnt > 1
Demo
SELECT MembershipNumber,
[status],
EmbossName
FROM (SELECT *,
Count(MembershipNumber)OVER(partition BY EmbossName) AS cnt
FROM (VALUES (11.0321,'active','John'),
(11.0322,'active','John'),
(23.0350,'active','Mary'),
(46.0383,'active','Fudge'),
(46.0382,'active','Fudge'),
(46.0381,'active','Fudge')) tc (MembershipNumber, [status], EmbossName)) A
WHERE cnt > 1

SELECT * FROM CARD a WHERE
(SELECT COUNT(*) FROM CARD b WHERE b.MembershipNumber = a.MembershipNumber) > 1
should do it

Select c.* from card c
join (select MembershipNumber from table group by
MembershipNumber having count(MembershipNumber) > 1) mem
on mem.MembershipNumber = c.MembershipNumber
Or
Select * from table where MembershipNumber in
(select MembershipNumber from table group by
MembershipNumber having count(MembershipNumber) > 1)

Find the duplicates on empbossname and get the result
select t1.* from card as t1 inner join
(select empbossname from card group by empbossname having count(*)>1) as t2
on t1.empbossname =t2.empbossname

Related

How to group and pick only certain values based on a field using select query SQL

I have a table as follow
ID
ORDERNO
1
123
1
123
2
456
2
456
During every select query done via application using JDBC, only the grouped records based on ORDERNO should be picked.
That means, for example, during first select query only details related to ID = 1, but we cannot specify the ID number in where clause because we do not know how many number of IDs will be there in future. So the query should yield only one set of records; application will delete those records after picking, hence next select query will result in picking other set of records. How to achieve it?
You can use TOP WITH TIES for this
SELECT TOP (1) WITH TIES
t.ID,
t.ORDERNO
FROM YourTable t
ORDER BY
t.ID;
If you want to select and delete at the same time you could delete using an OUTPUT clause
WITH cte AS (
SELECT TOP (1) WITH TIES
t.ID,
t.ORDERNO
FROM YourTable t
ORDER BY
t.ID
)
DELETE cte
OUTPUT deleted.*;
As one option you could select on the MIN(ID) like:
SELECT *
FROM yourtable
WHERE ID = (SELECT MIN(ID) FROM yourtable);
You could also use window functions to do this:
SELECT ID, ORDERNO
FROM
(
SELECT ID, ORDERNO
DENSE_RANK() OVER (ORDER BY ID ASC) AS dr
FROM yourtable
)dt
WHERE dr = 1;
order your rows and select top n number of rows that you want :
select top (1) with ties ID, ORDERNO
from tablename
order by ID asc

Returning the full record of each duplicated row by selecting the table and joining it to the duplicates?

The first query works. Query A is based on a post from StackOverflow (Using GROUP BY and HAVING COUNT(*) >1 to select duplicate and noon-duplicate field).
But is it possible to return the full record of each duplicated row by selecting the table and joining it to the duplicates? That's what I'm attempting in Query B. I'm trying to do so on two fields. Is it possible to accomplish this with the HAVING clause constructed this way? I'm a n00b. Any advice or education would be appreciated.
Query A) Based on an example from StackOverflow:
SELECT InstanceID, InstanceSequenceNumber
FROM [dbo].[ANBasics]
WHERE InstanceID IN
(SELECT InstanceID FROM [dbo].[ANBasics]
GROUP BY InstanceID
HAVING (COUNT(*) > 1))
ORDER BY InstanceID
Query B) What I'm trying to accomplish:
SELECT A.*, COUNT(*) AS B
FROM [dbo].[ANBasics] AS A
JOIN(
SELECT [InstanceID], [InstanceSequenceNumber], COUNT(*)
FROM [dbo].[ANBasics]
GROUP BY [InstanceID], [InstanceSequenceNumber]
HAVING (B > 1) )
ON A.[InstanceID] = B.[InstanceID]
AND A.[InstanceSequenceNumber] = B.[InstanceSequenceNumber]
ORDER BY A.[InstanceID]
If I understand correctly, window functions are the simplest solution:
SELECT ab.*
FROM (SELECT ab.*,
COUNT(*) OVER (PARTITION BY InstanceID, InstanceSequenceNumber) as cnt
FROM [dbo].[ANBasics] ab
) ab
WHERE cnt > 1;
If you want this for duplicates of two columns:
SELECT ab.*
FROM (SELECT ab.*,
COUNT(*) OVER (PARTITION BY InstanceID) as cnt
FROM [dbo].[ANBasics] ab
) ab
WHERE cnt > 1;

SQL query filtering on COUNT of a column

I need to filter a SQL query based on a count of records within that query.
I want the query to return only the rows where the count of "Location" is greater than 5.
For example, we have 100 rows of data. 10 "Locations" make up all 100 rows, but I only want the rows where the COUNT("Location") > 5, essentially eliminating the rows with Locations where the COUNT("Location") < 5.
I've tried combinations of aggregation and the HAVING clause but can't nail down the answer.
I think you want a window function:
select t.*
from (select t.*, count(*) over (partition by location) as cnt
from t
) t
where cnt >= 5;
Alternative answer from Gordon Linoff using CTE:
with CTE as(
select *, count(*) over (partition by Location) as count from table
)
select *from CTE where count >= 5
Here is the solution you may have been after by using the HAVING clause...
select t.*
from t
inner join
(
select Location, count(*) as Count
from t
group by Location
having count(*) >= 5
) as t2 on t.Location = t2.Location
order by t.ID
Here it is in action.

How to get the records from inner query results with the MAX value

The results are below. I need to get the records (seller and purchaser) with the max count- grouped by purchaser (marked with yellow)
You can use window functions:
with q as (
<your query here>
)
select q.*
from (select q.*,
row_number() over (order by seller desc) as seqnum_s,
row_number() over (order by purchaser desc) as seqnum_p
from q
) q
where seqnum_s = 1 or seqnum_p = 1;
Try this:
SELECT COUNT,seller,purchaser FROM YourTable ORDER BY seller,purchaser DESC
SELECT T2.MaxCount,T2.purchaser,T1.Seller FROM <Yourtable> T1
Inner JOIN
(
Select Max(Count) as MaxCount, purchaser
FROM <Yourtable>
GROUP BY Purchaser
)T2
On T2.Purchaser=T1.Purchaser AND T2.MaxCount=T1.Count
First you select the Seller from which will give you a list of all 5 sellers. Then you write another query where you select only the Purchaser and the Max(count) grouped by Purchaser which will give you the two yellow-marked lines. Join the two queries on fields Purchaser and Max(Count) and add the columns from the joined table to your first query.
I can't think of a faster way but this works pretty fast even with rather large queries. You can further-by order the fields as needed.

Inner join to check tables contain same values not working as expected

SELECT COUNT(1) FROM own.no_preselection_1_a;
SELECT COUNT(1) FROM own.no_preselection_1;
SELECT COUNT(1) FROM
(SELECT DISTINCT * FROM own.no_preselection_1_a
);
SELECT COUNT(1) FROM
(SELECT DISTINCT * FROM own.no_preselection_1
);
SELECT COUNT(1)
FROM OWN.no_preselection_1 t1
INNER JOIN OWN.no_preselection_1_a t2
ON t1.number = t2.number
AND t1.location_number = t2.location_number;
This returns:
COUNT(1)
----------------------
398
COUNT(1)
----------------------
398
COUNT(1)
----------------------
308
COUNT(1)
----------------------
308
COUNT(1)
----------------------
578
If we look at the visual explanation of joins here: http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html
The problem is on that last query. I would have thought that if the sets are the same (ie a perfect overlap), then the inner join would would return a set the size of the original sets.
Is the problem that each of the duplicates are creating entries for all of each other? (eg if there are 3 dupes of the same value on each table, it would create 3x3 = 9 entries for it?)
What's the solution here? (Just select the distincts to do the inner join on?) Is this a good test for checking if two tables contain the same data?
You have duplicates in your table, as the first and third, and second and fourth counts in your list make clear.
The join is working as it should, so there is no "problem". What are you trying to accomplish? Your goal is not being satisfied by the join.
I would suggest that you annotate your question with some actual data and the results that you want.
If you want to show that the two tables have the same values, you might try a union. Assuming that all the columns are the same in both tables and the columns in a row uniquely identify each row:
select t.*
from ((select '1' as which, t.*
from OWN.no_preselection_1 t
) union all
(select '1-a' as which, t.*
from OWN.no_preselection_1_a
)
) t
group by < all the columns in the tables >
having count(*) <> 1
If you are limited to the two columns and want to see if there are corresponding entries (with duplicates), the following works:
select t.*
from ((select '1' as which, number, location_number,
row_number() over (partition by number, location_number order by number) as seqnum
from OWN.no_preselection_1 t
) union all
(select '1-a' as which, number, location_number,
row_number() over (partition by number, location_number order by number) as seqnum
from OWN.no_preselection_1_a
)
) t
group by number, location_number, seqnum
having count(*) <> 1