Fetching multiple rows based on grouping - sql

Consider this data
PK field1 field2
1 a b
2 a (null)
3 x y
4 x z
5 q w
I need to get this data
select all columns from all rows where field1 has count >1
Which means the desired output is
PK field1 field2
1 a b
2 a (null)
3 x y
4 x z
i tried and finally settled for
select * from mytable where field1 in
(select field1 from mytable group by field1 having count(field1)>1 ) order by field1
but there has to be a better way than this

That's the way I would do it.
You could rewrite it with a join to the subquery instead of using in, but I doubt it would be any faster.
Edit: Ok, so for reference, the "join" method would go something like this:
select m.* from mytable m
join (
select field1 from mytable
group by field1
having count(field1)>1
) j on m.field1=j.field1
order by m.field1
And it seems it's worth testing to see if it's faster (thanks #binaryLV).

Another way, if using T-SQL
;WITH T AS
(
SELECT PK, FIELD1, FIELD2, COUNT(FIELD1) OVER(PARTITION BY FIELD1) AS R
)
SELECT PK, FIELD1, FIELD2
FROM T
WHERE R > 1

Related

Select unique field1 that has >1 distinct instances of field2 associated with it?

How can I query for the distinct field1 instances that have multiple distinct corresponding field2 values?
field1
field2
a
apple
b
grape
c
banana
b
orange
a
apple
In this example I want to return "b", since there are at least 2 distinct values (grape and orange) for field2 that correspond to it. I don't wan't "a" since there is only 1 unique field2 value that corresponds, "apple".
I have tried
with all_unique_combos as (
select distinct field1, field2
from table
)
select field1
from all_unique_combos
group by field1
having count(field2) > 1
I actually think this is right and would give me what I need. But at the moment it's returning 0 rows so I kinda need a sanity check. Thanks for any input either way.
You can use aggregation:
select field1
from t
group by field1
having min(field2) <> max(field2);
A straight-forward approach uses group by and having:
select field1
from mytable
group by field1
having min(field2) <> max(field2)
Using COUNT(DISTINCT ...):
select field1
from tab
group by field1
having count(disitnct field2) > 1

Get max value from result which contains different string value in group by clause in SQL Server

My table is like this,
Field1 | Field2 | Field3
2 | 100 | test1
3 | 100 | test2
I need to get max from this result. so the result should be as follows,
3 100 test2
my current query is,
SELECT MAX(Field1),Field2,Field3 FROM Table1 GRUOP BY Field2,Field3
this returns these two rows. but i need only the row which contain the MAX(Field1) value.
Presumably, you want the row that has the maximum field1 for each distinct field2. Since you want the entire row, aggregation is not the solution; instead, you want to filter.
Here is one way to do it using a correlated subquery:
select t.*
from mytable t
where t.field1 = (select max(t1.field1) from mytable t1 where t1.field2 = t.field2)
Another option uses window functions:
select *
from (
select t.*, rank() over(partition by field2 order by field1 desc) rn
from mytable t
) t
where rn = 1
Finally, here is a more original approach that uses with ties:
select top (1) with ties *
from mytable
order by rank() over(partition by field2 order by field1 desc)

MS Access SQL Query - Find record order

would like to ask how do we find out the 'numbering order' of a record.
My sql query -
SELECT *
FROM tableName
WHERE field2=444
ORDER BY field1
field1 field2
1) 2/9/17 111
2) 3/9/17 222
3) 5/9/17 333
4) 8/9/17 444
5) 9/9/17 555
It would return 4 as 444 is on the Fourth record. Please advice.
p/s - we hv a large DB so select * and compare each will be not efficient
Thank you,
You can use a subquery or DCount to count all rows lower than the previous one:
SELECT (SELECT Count(Field1) FROM tableName As B WHERE b.Field1 <= a.Field1) As numberingOrder, *
FROM tableName As A
WHERE field2=444
ORDER BY field1
And for only the distinct values, as asked in comments:
SELECT (
SELECT Count(Field1)
FROM (
SELECT DISTINCT Field1 FROM tableName
) As B
WHERE b.Field1 <= a.Field1
) As numberingOrder, *
FROM tableName As A
WHERE field2=444
ORDER BY field1
You can maybe do this:
SELECT COUNT(*) as Position_Of_Where_Clause
FROM YourTable t
WHERE t.field1 <= (SELECT TOP 1 s.field1
FROM YourTable s
WHERE s.field2 = 444
ORDER BY s.field1)
If you want the fourth record and the values are all distinct, then you can use SELECT TOP twice:
SELECT TOP 1 t.*
FROM (SELECT TOP 4 t.*
FROM tableName as t
WHERE field2 = 444
ORDER BY field1
) as t
ORDER BY field1 DESC;

Inserting a unique int into a non primary key field

I'm trying to make an SQL query using INSERT INTO to copy a number of rows from a table, but I want one of the fields (which isn't a primary key) to have a new, unique, int (I know this is terrible database design, but I can't change the structure of the DB).
Here is a simplified example of what I'm trying to do:
INSERT INTO Mytable
(field1
,field2
,field3
,nonKeyUniqueInt)
SELECT
(field1
,field2
,field3
,(SELECT MAX(nonKeyUniqueInt)+1 FROM mytable)
FROM
mytable
WHERE
(conditions)
However this doesn't work because the SELECT MAX query only runs once, giving all my new rows the same value for that field. Given the following rows to copy:
field1 field2 field3 nonKeyUniqueInt
x y z 1
a b c 2
I get output of:
field1 field2 field3 nonKeyUniqueInt
x y z 1
a b c 2
x y z 3
a b c 3
Is what I'm trying to do possible?
The problem is that the subquery gets evaluated once for the insert, not once per row. The solution is to use row_number():
INSERT INTO Mytable(field1, field2, field3, nonKeyUniqueInt)
SELECT field1, field2, field3,
x.maxk + row_number() over (order by (select NULL))
FROM mytable CROSS JOIN
(SELECT MAX(nonKeyUniqueInt) as maxk FROM mytable) x
WHERE (conditions);
I moved the max calculation to the FROM clause to make it clear that it is evaluated only once.

SQL counting total rows with distinct?

i need a complex query:
Consider this table:
ID - field1 - field2
=================
1 a 10
2 a 10
3 a 20
4 b 20
i need a query that counts the total record grouped by field1 and field2. I mean i need this result:
field - count
==================
field1 a - 3
field1 b - 1
field2 10 - 2
field2 20 - 2
maybe i need to do 2 query for each field i need the count?
SELECT field1, COUNT( * ) FROM t1 GROUP BY field1
?
Thanks for any suggestions
You do need two SELECTs, but you can get them to return a single result set as follows. Note that you need to CAST the first SELECT so that the values are compatible with the text field in the second SELECT:
SELECT 'field1' AS FieldName, CAST(field1 AS CHAR) AS FieldValue, COUNT(*) AS Count
FROM table GROUP BY field1
UNION ALL
SELECT 'field2' AS FieldName, field2 AS FieldValue, COUNT(*) AS Count
FROM table GROUP BY field2