SQL: Retrieve value from a column that occurred least number of times - sql

I have a table which have a single field. and it have a values like (3,7,9,11,7,11)
Now I want a query which will pick the value that occurred least number of times and if there is a tie with minimum occurrences then use the smallest number
In this case the answer will be 3.

Something like this:
SELECT TOP 1 COUNT(*), myField
FROM myTable
GROUP BY (myField)
ORDER BY COUNT(*) ASC
ADDITIONAL: And to taking into account the tie-breaker situation:
SELECT TOP 1 COUNT(*), myField
FROM myTable
GROUP BY (myField)
ORDER BY COUNT(*) ASC, myField ASC

In MySQL and PostgreSQL:
SELECT *
FROM (
SELECT field, COUNT(*) AS cnt
FROM mytable
GROUP BY
field
) q
ORDER BY
cnt, field
LIMIT 1

Assuming you're using SQL Server: if you have ties for the least frequent number, and you want all ties returned, then you could do something like this:
DECLARE #temp table (
count int,
myField int
)
INSERT #temp
SELECT COUNT(*), myField
FROM myTable
GROUP BY (myField)
DECLARE #minCount int
SELECT #minCount = MIN(count)
FROM #temp
SELECT count, myField
FROM #temp
WHERE count = #minCount

Related

How to change a UNION to a IN clause?

I need to get a maximum of 3 distinct records from the same table, so currently I'm doing:
SELECT 1, mycolumn FROM mytable WHERE id = #firstId
UNION ALL
SELECT 2, mycolumn FROM mytable WHERE id = #secondId
UNION ALL
SELECT 3, mycolumn FROM mytable WHERE id = #thirdId
The actual SELECT part contains over 20 columns and the FROM part contains a number of JOINs. The first column is a constant and is always fixed depending on the record. I don't know how many records might return. It could be anything from 0 to 3 records.
Is it possible to change the above query so that it uses IN like this:
SELECT ???, mycolumn FROM mytable WHERE id IN (#firstId, #secondId, #thirdId)
But how do I explicitly map each record to the fixed constant if I use IN?
You may use a CASE expression here with a single query:
SELECT
CASE id WHEN #firstId THEN 1
WHEN #secondId THEN 2
WHEN #thirdId THEN 3 END AS val,
mycolumn
FROM mytable
WHERE
id IN (#firstId, #secondId, #thirdId);
If you wish to also order by the computed column, then add ORDER BY val to the end of the above query.
You can use CASE like following.
SELECT
CASE
WHEN id= #firstId THEN 1
WHEN id=#secondId THEN 2
ELSE 3
END AS rn,
mycolumn
FROM mytable
WHERE id IN (#firstId,
#secondId,
#thirdId)
Another approach can be using DENSE_RANK if you have one record for each provided id and #firstId, #secondId & #thirdId are in ascending order.
SELECT DENSE_RANK()
OVER(
ORDER BY id) rn,
mycolumn
FROM mytable
WHERE id IN ( #firstId, #secondId, #thirdId )
I would recommend a table-valued constructor for this purpose:
select v.outputnum, my_column
from mytable t join
(values (#firstid, 1),
(#secondid, 2),
(#thirdid, 3)
) v(id, outputnum)
on t.id = v.id
order by v.outputnum;
I think this is simpler than other versions, because the list of ids is only present once in the query -- so no danger of different parts of the query getting out of sync.

Find the unique value in column MS SQL database

I have a set of data as below
number quantity
1 4
2 6
3 7
4 9
2 1
1 2
5 4
I need to find the unique value in the column "number"
The output should look like this:
number quantity
3 7
4 9
5 4
Any help would be appreciated. I am using MS SQL
In the inner query get all the distinct numbers, then join with again with the main table to get your expected results.
select o.*
from mytable o , (select number
from mytable
group by number) dist
where o.number = dist.number
One way to go could be to have an aggregate query that counts the number of occurrences for each number use it in a subquery:
SELECT number, quantity
FROM my_table
WHERE number IN (SELECT number
FROM my_table
GROUP BY number
HAVING COUNT(*) = 1)
If your column name is my_column in table my_table, the query is:
SELECT my_column, COUNT(*) as count
FROM my_table
GROUP BY my_column
HAVING COUNT(*) > 1
This will return all records that have duplicate my_column content, as well as how many times this content occurs in the database.
you can use below code for desire output:
SELECT DISTINCT(my_column), COUNT(*) as count
FROM my_table
GROUP BY my_column
Try this :
SELECT *
FROM yourtable t1
WHERE (SELECT Count(*)
FROM yourtable t2
WHERE t1.number = t2.number) = 1
Query in where clause will return number of occurrences of each number and checking it with 1 will return only those rows will have only one occurrence in table.
You can probably use ROW_NUMBER() analytic function like
select * from
(
select number,
quantity,
ROW_NUMBER() OVER(PARTITION BY number ORDER BY number) AS rn
from table1
) tab where rn = 1;
Try this:
create table #TableName(number int, quantity int)
insert into #TableName values(1, 2)
insert into #TableName values(1, 4)
insert into #TableName values(2, 4)
SELECT number, quantity
FROM #TableName
WHERE number
IN(SELECT number
FROM #TableName
GROUP BY number
HAVING COUNT(NUMBER) = 1)

Simple SQL query

I have a table, with these columns:
ID | Data
How to find out which record has highest ID?
To get the largest ID:
select max(ID) from myTable
To get a record that has the largest ID:
select *
from MyTable
where ID = (Select max(ID) from myTable)
select *
from YourTable
where ID = (select max(ID) from YourTable)
select max(ID) from tablename
As well as max, you can use TOP on SQL Server
select TOP 1 * from myTable order by id desc
For joint top
select TOP 1 WITH TIES * from myTable order by id desc
Other engines have LIMIT not TOP. This can give the whol record without a separate MAX sub-query too

Select top and bottom rows

I'm using SQL Server 2005 and I'm trying to achieve something like this:
I want to get the first x rows and the last x rows in the same select statement.
SELECT TOP(5) BOTTOM(5)
Of course BOTTOM does not exist, so I need another solution. I believe there is an easy and elegant solution that I'm not getting. Doing the select again with GROUP BY DESC is not an option.
Using a union is the only thing I can think of to accomplish this
select * from (select top(5) * from logins order by USERNAME ASC) a
union
select * from (select top(5) * from logins order by USERNAME DESC) b
Check the link
SQL SERVER – How to Retrieve TOP and BOTTOM Rows Together using T-SQL
Did you try to using rownumber?
SELECT *
FROM
(SELECT *, ROW_NUMBER() OVER (Order BY columnName) as TopFive
,ROW_NUMBER() OVER (Order BY columnName Desc) as BottomFive
FROM Table
)
WHERE TopFive <=5 or BottomFive <=5
http://www.sqlservercurry.com/2009/02/select-top-n-and-bottom-n-rows-using.html
I think you've two main options:
SELECT TOP 5 ...
FROM ...
ORDER BY ... ASC
UNION
SELECT TOP 5 ...
FROM ...
ORDER BY ... DESC
Or, if you know how many items there are in the table:
SELECT ...
FROM (
SELECT ..., ROW_NUMBER() OVER (ORDER BY ... ASC) AS intRow
FROM ...
) AS T
WHERE intRow BETWEEN 1 AND 5 OR intRow BETWEEN #Number - 5 AND #Number
Is it an option for you to use a union?
E.g.
select top 5 ... order by {specify columns asc}
union
select top 5 ... order by {specify columns desc}
i guess you have to do it using subquery only
select * from table where id in (
(SELECT id ORDER BY columnName LIMIT 5) OR
(SELECT id ORDER BY columnName DESC LIMIT 5)
)
select * from table where id in (
(SELECT TOP(5) id ORDER BY columnName) OR
(SELECT TOP(5) id ORDER BY columnName DESC)
)
EDITED
select * from table where id in (
(SELECT TOP 5 id ORDER BY columnName) OR
(SELECT TOP 5 id ORDER BY columnName DESC)
)
No real difference between this and the union that I'm aware of, but technically it is a single query.
select t.*
from table t
where t.id in (select top 5 t2.id from table t2 order by MyColumn)
or
t.id in (select top 5 t2.id from table t2 order by MyColumn desc);
SELECT *
FROM (
SELECT x, rank() over (order by x asc) as rown
FROM table
) temp
where temp.rown = 1
or temp.rown = (select count(x) from table)
Then you are out - doing the select again IS the only option, unless you want to pull in the complete result set and then throwing away everything in between.
ANY sql I cna think of is the same way - for the bottom you need to know first either how many items you have (materialize everything or use count(*)) or a reverse sort order.
Sorry if that does not suit you, but at the end.... reality does not care, and I do not see any other way to do that.
I had to do this recently for a very large stored procedure; if your query is quite large, and you want to minimize the amount of queries you could declare a #tempTable, insert into that #tempTable then query from that #tempTable,
DECLARE #tempTable TABLE ( columns.. )
INSERT INTO #tempTable
VALUES ( SELECT.. your query here ..)
SELECT TOP(5) columns FROM #tempTable ORDER BY column ASC -- returns first to last
SELECT TOP(5) columns FROM #tempTable ORDER BY column DESC -- returns last to first

the row no in query output

I have a numeric field (say num) in table along with pkey.
select * from mytable order by num
now how I can get the row no in query output of a particular row for which I have pkey.
I'm using sql 2000.
Sounds like you want a row number for each record returned.
In SQL 2000, you can either do this:
SELECT (SELECT COUNT(*) FROM MyTable t2 WHERE t2.num <= t.num) AS RowNo, *
FROM MyTable t
ORDER BY num
which assumes num is unique. If it's not, then you'd have to use the PK field and order by that.
Or, use a temp table (or table var):
CREATE TABLE #Results
(
RowNo INTEGER IDENTITY(1,1),
MyField VARCHAR(10)
)
INSERT #Results
SELECT MyField
FROM MyTable
ORDER BY uum
SELECT * FROM #Results
DROP TABLE #Results
In SQL 2005, there is a ROW_NUMBER() function you could use which makes life a lot easier.
as i understand your question you want to get the number of all rows returned, right?
if so use ##rowcount
As Ada points out, this task became a lot easier in SQL Server 2005....
SELECT whatever, RowNumber from (
SELECT pk
, whatever
, ROW_NUMBER() OVER(ORDER BY num) AS 'RowNumber'
FROM mytable
)
WHERE pk = 23;