Retrieve the most used 10 records - sql

I want to retrieve the most used 10 records in a field in my database. I used this query but it didn't work !
select Top 10 tag from articles order by count(tag) desc ;
This is the error I'm getting:
Column 'article.tags' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

Try this:
SELECT TOP 10 tag, COUNT(tag) tagCount
FROM articles
GROUP BY tag
ORDER BY tagCount DESC

Select TOP 10 tag From
(
Select tag,count(*) as total
From articles
Group by tag
) z
order by total Desc

You can't identify with a simple select top statement. I would suggest you to involve one more table to keep track of id of most selected record something like this:
ArticleId Counter LastUsed
--------------------------
1 5 11/12/2013
3 11 10/12/2013 // and so on
Using this table join with your main table and pick the mostly used top 10 ids, based on their counter.
Select * From MainTable Where ArticleId in (
Select Top(10) ArticleId
From Table
Order By Counter Desc)

Related

MS Access TRIMMEAN how to

I need to perform TREAMMEAN in Access, which does not have this function.
In a table I have many Employees, each has many records.
I need to TRIMMEAN Values for each Employee separately.
Following queries perform TOP 10 percent for all records:
qry_data_TOP10_ASC
qry_data_TOP10_DESC
unionqry_TOP10_ASCandDESC
qry_data_ALL_minus_union_qry
After that, I can use Avg (Average).
But I don't know how to do it for each employee.
Visualization:
Note:
This question is edited to simplify problem.
You don't really give information in your pseudo code about your data fields but using your example that DOES have basic field information I can suggest the following should work as you described
It assumes field1 is your unique record ID - but you make no mention of which fields are keys
SELECT AVG(qry_data.field2) FROM qry_data WHERE qry_data.field1 NOT IN
(SELECT * FROM
(SELECT TOP 10 PERCENT qry_data.field1, qry_data.field2
FROM qry_data
ORDER BY qry_data.field2 ASC)
UNION
(SELECT TOP 10 PERCENT qry_data.field1, qry_data.field2
FROM qry_data
ORDER BY qry_data.field2 DESC)
)
This should give you what you want, the two sub-queries should correlate the TOP 10s (ascending and descending) for every employee. The two NOT INs should then remove those from the Table1 records and then you group the Employees and Average the Scores.
SELECT Table1.Employee, AVG(Table1.Score) AS AvgScore
FROM Table1
WHERE ID NOT IN
(
SELECT TOP 10 ID
FROM Table1 a
WHERE a.Employee = Table1.Employee
ORDER BY Score ASC, Employee, ID
)
AND ID NOT IN
(
SELECT TOP 10 ID
FROM Table1 b
WHERE b.Employee = Table1.Employee
ORDER BY Score DESC, Employee, ID
)
GROUP BY Table1.Employee;

delete overflow record per ID

i need to have 4 records or less per ID. some ID's have more than 4 records. I need to delete the records above the limit so i have 4 records per ID.
i tried many things but the only solution i found is just deleting all the records when the ID has more than 4. this is my code for getting the ammount of records per ID:
select count(voorwerpnummer) AS plaatjes, voorwerpnummer
from Illustraties INNER JOIN items
ON Illustraties.itemID = items.ID
INNER JOIN tbl_voorwerp
ON items.ID = tbl_voorwerp.voorwerpnummer
group by voorwerpnummer
order by plaatjes DESC
i have this line to delete the extra records per itemID:
DELETE FROM illustraties
WHERE plaatjefile NOT IN (select top 4 plaatjefile from illustraties where itemID = 110769395358)
AND itemID = 110769395358
now i need to itterate through all the itemID's which have more than 4 records.
this is how to get all the itemID's with more than 4 records:
WITH cte AS
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY itemID ORDER BY itemID) AS rn
FROM illustraties
)
SELECT distinct ItemID
FROM cte
WHERE rn > 4
can anyone make me a function or something to go through all those itemID's and execute that delete statement?
OR make a query which adds a rownumber per ID.
for example : an ID has 5 records. the 5 records get the numbers 1 to 5. the next ID has 8 records. the 8 records get the numbers 1 to 8.
this way i can delete the records which have an rownumber of 5 or higher.
It is little known that you can delete from a CTE or derived table:
WITH cte AS
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY itemID ORDER BY itemID) AS rn
FROM illustraties
)
DELETE cte
FROM cte
WHERE rn > 4
I just changed one line. Your ORDER BY should really create a total order. If not SQL Server has some freedom which records to delete. Might be arbitrary and not in your interest.
Hope you need to delete records from Illustraties table.Is that possible for you to share the table structure along with Unique key fields for that table.

How to find first duplicate row in a table sql server

I am working on SQL Server. I have a table, that contains around 75000 records. Among them there are several duplicate records. So i wrote a query to know which record repeated how many times like,
SELECT [RETAILERNAME],COUNT([RETAILERNAME]) as Repeated FROM [Stores] GROUP BY [RETAILERNAME]
It gives me result like,
---------------------------
RETAILERNAME | Repeated
---------------------------
X | 4
---------------------------
Y | 6
---------------------------
Z | 10
---------------------------
Among 4 record(s) of X record, i need take only first record of X.
so here i want to retrieve all fields from first row of duplicate records. i.e. Take all records whose RETAILERNAME='X' we will get some no. of duplicate records, we need to get only first row from them.
Please guide me.
You could try using ROW_NUMBER.
Something like
;WITH Vals AS (
SELECT [RETAILERNAME],
ROW_NUMBER() OVER(PARTITION BY [RETAILERNAME] ORDER BY [RETAILERNAME]) RowID
FROM [Stores ]
)
SELECT *
FROm Vals
WHERE RowID = 1
SQL Fiddle DEMO
You can then also remove the duplicates if need be (BUT BE CAREFUL THIS IS PERMANENT)
;WITH Vals AS (
SELECT [RETAILERNAME],
ROW_NUMBER() OVER(PARTITION BY [RETAILERNAME] ORDER BY [RETAILERNAME]) RowID
FROM Stores
)
DELETE
FROM Vals
WHERE RowID > 1;
You Can write query as under
SELECT TOP 1 * FROM [Stores] GROUP BY [RETAILERNAME]
HAVING your condition
WITH cte
AS (SELECT [retailername],
Row_number()
OVER(
partition BY [retailername]
ORDER BY [retailername])'RowRank'
FROM [retailername])
SELECT *
FROM cte

adding count( ) column on each row

I'm not sure if this is even a good question or not.
I have a complex query with lot's of unions that searches multiple tables for a certain keyword (user input). All tables in which there is searched are related to the table book.
There is paging on the resultset using LIMIT, so there's always a maximum of 10 results that get withdrawn.
I want an extra column in the resultset displaying the total amount of results found however. I do not want to do this using a separate query. Is it possible to add a count() column to the resultset that counts every result found?
the output would look like this:
ID Title Author Count(...)
1 book_1 auth_1 23
2 book_2 auth_2 23
4 book_4 auth_.. 23
...
Thanks!
This won't add the count to each row, but one way to get the total count without running a second query is to run your first query using the SQL_CALC_FOUND_ROWS option and then select FOUND_ROWS(). This is sometimes useful if you want to know how many total results there are so you can calculate the page count.
Example:
select SQL_CALC_FOUND_ROWS ID, Title, Author
from yourtable
limit 0, 10;
SELECT FOUND_ROWS();
From the manual:
http://dev.mysql.com/doc/refman/5.1/en/information-functions.html#function_found-rows
The usual way of counting in a query is to group on the fields that are returned:
select ID, Title, Author, count(*) as Cnt
from ...
group by ID, Title, Author
order by Title
limit 1, 10
The Cnt column will contain the number of records in each group, i.e. for each title.
Regarding second query:
select tbl.id, tbl.title, tbl.author, x.cnt
from tbl
cross join (select count(*) as cnt from tbl) as x
If you will not join to other table(s):
select tbl.id, tbl.title, tbl.author, x.cnt
from tbl, (select count(*) as cnt from tbl) as x
My Solution:
SELECT COUNT(1) over(partition BY text) totalRecordNumber
FROM (SELECT 'a' text, id_consult_req
FROM consult_req cr);
If your problem is simply the speed/cost of doing a second (complex) query I would suggest you simply select the resultset into a hash-table and then count the rows from there while returning, or even more efficiently use the rowcount of the previous resultset, then you do not even have to recount
This will add the total count on each row:
select count(*) over (order by (select 1)) as Cnt,*
from yourtable
Here is your answare:
SELECT *, #cnt count_rows FROM (
SELECT *, (#cnt := #cnt + 1) row_number FROM your_table
CROSS JOIN (SELECT #cnt := 0 AS variable) t
) t;
You simply cannot do this, you'll have to use a second query.

Selecting Nth Record in an SQL Query

I have an SQL Query that i'm running but I only want to select a specific row. For example lets say my query was:
Select * from Comments
Lets say this returns 10 rows, I only want to select the 8th record returned by this query. I know I can do:
Select Top 5 * from Comments
To get the top 5 records of that query but I only want to select a certain record, is there anything I can put into this query to do that (similar to top).
Thanks
jack
This is a classic interview question.
In Ms SQL 2005+ you can use the ROW_NUMBER() keyword and have the Predicate ROW_NUMBER = n
USE AdventureWorks;
GO
WITH OrderedOrders AS
(
SELECT SalesOrderID, OrderDate,
ROW_NUMBER() OVER (ORDER BY OrderDate) AS 'RowNumber'
FROM Sales.SalesOrderHeader
)
SELECT *
FROM OrderedOrders
WHERE RowNumber = 5;
In SQL2000 you could do something like
SELECT Top 1 *FROM
[tblApplications]
where [ApplicationID] In
(
SELECT TOP 5 [ApplicationID]
FROM [dbo].[tblApplications]
order by applicationId Desc
)
How about
SELECT TOP 1 * FROM
(SELECT TOP 8 * FROM Comments ORDER BY foo ASC)
ORDER BY foo DESC
First, you should say which RDBMS you're using.
Second, you should give careful thought to what it is you're trying to accomplish. Relational Databases are set-based. In general, the order of elements in a set does not matter. You'll want to ask why it matters in this case, then see if there's a better way to embed the concept of order into the query itself.
For instance, in SQL Server 2005 (and other RDBMS), you can use the ROW_NUMBER function to assign a sequential number to each row returned, based on the criteria you specify. You could then select rows based on the row number. Example from Books Online:
USE AdventureWorks;
GO
WITH OrderedOrders AS
(
SELECT SalesOrderID, OrderDate,
ROW_NUMBER() OVER (ORDER BY OrderDate) AS 'RowNumber'
FROM Sales.SalesOrderHeader
)
SELECT *
FROM OrderedOrders
WHERE RowNumber BETWEEN 50 AND 60;
SELECT * FROM comments WHERE ...conditions... LIMIT 1 OFFSET 8
OFFSET is a good thing for MySQL
For SQL Server 2005:
select rank() OVER (ORDER BY c.subject, c.date) as rank, c.subject, c.date
from comments c
where rank = 8
Well, in T-SQL (the dialect for SQL Server) you can do the following:
SELECT TOP 1 *
FROM (SELECT TOP 8 *
FROM Table
ORDER
BY SortField)
ORDER
BY SortField DESC
This way you get the 8th record.
I have read the question & your comments on you would want next 3 blog comments etc.
How is your tables structured?
Assume that you have blog post Id & comment Id is generated in ascending order for each blog post, you could do a SELECT based on the current Id.
e.g. if the blogpostId = 101, you get the top 3 comments order by posted Id. Now lets say, you want to get the next 3 comments - you could do a SELECT WHERE commentId between the last comment id shown TO the comment id - 3
But all that depends on how your tables are defined.
In SQL 2000 where you do not have ROW_NUMBER() function you could use a work-around like this:
SELECT CommentsTableFieldList, IDENTITY(INT, 1,1) as seqNo
INTO #SeqComments
FROM Comments
SELECT * FROM #SeqComments
WHERE seqNo = 8
select top 1 *
from TableName
where ColumnName1 in
(
select top nth ColumnName1
from TableName
order by ColumnName1 desc
)
order by ColumnName1 desc
From the SELECT reference, use the LIMIT keyword:
SELECT * FROM tbl LIMIT 5,10; # Retrieve rows 6-15
SELECT * FROM tbl LIMIT 5; # Retrieve first 5 rows
Note: this is for MySQL, other SQL engines may have a different keyword.
Select from tablename limit nthrow,1;
try This
Let us assume , We want select 5th row of WC_Video Table
And
Select * from (Select Row_Number() over (Order by Uploadedon) as 'rownumber',* from Wc_Video )as Temp where rownumber=5