SQL optimization : select distinct from one table - sql

Suppose I have got a SQL like this
select distinct CUSTOMER_PRODUCT_ORDER as ORDER
from MASTER_LIST
where PROJECT_ID = "ABCDD"
order by ORDER ASC
how can I optimize the performance of running this sql ?

I think that with a group by would be better and more performant in most cases :
select CUSTOMER_PRODUCT_ORDER as ORDER
from MASTER_LIST
where PROJECT_ID = "ABCDD"
GROUP BY CUSTOMER_PRODUCT_ORDER
order by ORDER ASC

Related

Order by DESC reverse result

I'm retrieving some data in SQL, order by DESC. I then want to reverse the result. I was doing this by pushing the data into an array and then using array_reverse, but I am finding it's quite taxing on CPU time and would like to simply use the correct SQL query.
I've looked at this thread SQL Server reverse order after using desc, but I cannot seem to make it work with my query.
SELECT live.message,
live.sender,
live.sdate,
users.online
FROM live, users
WHERE users.username = live.sender
ORDER BY live.id DESC
LIMIT 15
You can place your query into a subquery and then reverse the order:
SELECT t.message,
t.sender,
t.sdate,
t.online
FROM
(
SELECT live.id,
live.message,
live.sender,
live.sdate,
users.online
FROM live
INNER JOIN users
ON users.username = live.sender
ORDER BY live.id DESC
LIMIT 15
) t
ORDER BY t.id ASC
You'll notice that I replaced your implicit JOIN with an explicit INNER JOIN. It is generally considered undesirable to use commas in the FROM clause (q.v. the ANSI-92 standard) because it makes the query harder to read.
You could wrap your query with another query and order by with asc. Since you want to order by live.id, you must include it in the inner query so the outer one can sort by it:
SELECT message, sender, sdate, online
FROM (SELECT live.message, live.sender, live.sdate, users.online, live.id
FROM live, users
WHERE users.username = live.sender
ORDER BY live.id DESC
LIMIT 15) t
ORDER BY id ASC

Squeryl order by multiple columns

I need to order by 2 fields:
SELECT * FROM item ORDER BY date ASC, sequence DESC;
Is it possible to emulate this SQL with Squeryl?
You can order by multiple fields. Just add them to the orderByclause as below:
from(table)(t => select(t) orderBy(t.date, t.sequence desc)

Joining translate table, keeping order form indexes in SQLite

I use this SQL to grab some indexes:
select follow
from unigram
where alternativeSpelling like 'test'
order by freq desc
limit 10;
I then convert them to words using this SQL, one by one:
select word
from wordIdxTranslate
where word_idx = <one of the indexes from above>
How do I combine these to a single query, whil epreserving the ranking order from the first query ("freq")?
Untested, but this should do it:
SELECT word
FROM unigram, wordIdxTranslate
WHERE
unigram.follow=wordIdxTranslate.word_idx
AND
unigram.follow IN (SELECT T1.follow
FROM unigram AS T1
WHERE T1.alternativeSpelling LIKE 'test'
ORDER BY T1.freq DESC
LIMIT 10)
ORDER BY freq DESC
One option would be to combine the queries with a join, like:
select word
from (
select follow
, freq
from unigram
where alternativeSpelling like 'test'
order by
freq desc
limit 10
) uni
join wordIdxTranslate wit
on wit.word_idx = uni.follow
order by
uni.freq desc

Complex SQL pagination Query

I am doing pagination for my data using the solution to this question.
I need to be using this solution for a more complex query now. Ie. the SELECT inside the bracket has joins and aggregate functions.
This is that solution I'm using as a reference:
;WITH Results_CTE AS
(
SELECT
Col1, Col2, ...,
ROW_NUMBER() OVER (ORDER BY SortCol1, SortCol2, ...) AS RowNum
FROM Table
WHERE <whatever>
)
SELECT *
FROM Results_CTE
WHERE RowNum >= #Offset
AND RowNum < #Offset + #Limit
The query that I need to incorporate into the above solution:
SELECT users.indicator, COUNT(*) as 'queries' FROM queries
INNER JOIN calls ON queries.call_id = calls.id
INNER JOIN users ON calls.user_id = users.id
WHERE queries.isresolved=0 AND users.indicator='ind1'
GROUP BY users.indicator ORDER BY queries DESC
How can I achieve this? So far I've made it work by removing the ORDER BY queries DESC part and putting that in the line ROW_NUMBER() OVER (ORDER BY ...) AS RowNum, but when I do this it doesn't allow me to order by that column ("Invalid column name 'queries'.").
What do I need to do to get it to order by this column?
edit: using SQL Server 2008
Try ORDER BY COUNT(*) DESC . It works on MySQL ... not sure about SQL Server 2008
I think queries your alias name for count(*) column
then use like this
SELECT users.indicator, COUNT(*) as 'queries' FROM queries
INNER JOIN calls ON queries.call_id = calls.id
INNER JOIN users ON calls.user_id = users.id
WHERE queries.isresolved=0 AND users.indicator='ind1'
GROUP BY users.indicator ORDER BY COUNT(*) DESC
http://oops-solution.blogspot.com/2011/11/string-handling-in-javascript.html

How to use DISTINCT and ORDER BY in same SELECT statement?

After executing the following statement:
SELECT Category FROM MonitoringJob ORDER BY CreationDate DESC
I am getting the following values from the database:
test3
test3
bildung
test4
test3
test2
test1
but I want the duplicates removed, like this:
bildung
test4
test3
test2
test1
I tried to use DISTINCT but it doesn't work with ORDER BY in one statement. Please help.
Important:
I tried it with:
SELECT DISTINCT Category FROM MonitoringJob ORDER BY CreationDate DESC
it doesn't work.
Order by CreationDate is very important.
The problem is that the columns used in the ORDER BY aren't specified in the DISTINCT. To do this, you need to use an aggregate function to sort on, and use a GROUP BY to make the DISTINCT work.
Try something like this:
SELECT DISTINCT Category, MAX(CreationDate)
FROM MonitoringJob
GROUP BY Category
ORDER BY MAX(CreationDate) DESC, Category
Extended sort key columns
The reason why what you want to do doesn't work is because of the logical order of operations in SQL, as I've elaborated in this blog post, which, for your first query, is (simplified):
FROM MonitoringJob
SELECT Category, CreationDate i.e. add a so called extended sort key column
ORDER BY CreationDate DESC
SELECT Category i.e. remove the extended sort key column again from the result.
So, thanks to the SQL standard extended sort key column feature, it is totally possible to order by something that is not in the SELECT clause, because it is being temporarily added to it behind the scenes.
So, why doesn't this work with DISTINCT?
If we add the DISTINCT operation, it would be added between SELECT and ORDER BY:
FROM MonitoringJob
SELECT Category, CreationDate
DISTINCT
ORDER BY CreationDate DESC
SELECT Category
But now, with the extended sort key column CreationDate, the semantics of the DISTINCT operation has been changed, so the result will no longer be the same. This is not what we want, so both the SQL standard, and all reasonable databases forbid this usage.
Workarounds
It can be emulated with standard syntax as follows
SELECT Category
FROM (
SELECT Category, MAX(CreationDate) AS CreationDate
FROM MonitoringJob
GROUP BY Category
) t
ORDER BY CreationDate DESC
Or, just simply (in this case), as shown also by Prutswonder
SELECT Category, MAX(CreationDate) AS CreationDate
FROM MonitoringJob
GROUP BY Category
ORDER BY CreationDate DESC
I have blogged about SQL DISTINCT and ORDER BY more in detail here.
If the output of MAX(CreationDate) is not wanted - like in the example of the original question - the only answer is the second statement of Prashant Gupta's answer:
SELECT [Category] FROM [MonitoringJob]
GROUP BY [Category] ORDER BY MAX([CreationDate]) DESC
Explanation: you can't use the ORDER BY clause in an inline function, so the statement in the answer of Prutswonder is not useable in this case, you can't put an outer select around it and discard the MAX(CreationDate) part.
Just use this code, If you want values of [Category] and [CreationDate] columns
SELECT [Category], MAX([CreationDate]) FROM [MonitoringJob]
GROUP BY [Category] ORDER BY MAX([CreationDate]) DESC
Or use this code, If you want only values of [Category] column.
SELECT [Category] FROM [MonitoringJob]
GROUP BY [Category] ORDER BY MAX([CreationDate]) DESC
You'll have all the distinct records what ever you want.
2) Order by CreationDate is very important
The original results indicated that "test3" had multiple results...
It's very easy to start using MAX all the time to remove duplicates in Group By's... and forget or ignore what the underlying question is...
The OP presumably realised that using MAX was giving him the last "created" and using MIN would give the first "created"...
if object_id ('tempdb..#tempreport') is not null
begin
drop table #tempreport
end
create table #tempreport (
Category nvarchar(510),
CreationDate smallint )
insert into #tempreport
select distinct Category from MonitoringJob (nolock)
select * from #tempreport ORDER BY CreationDate DESC
Distinct will sort records in ascending order. If you want to sort in desc order use:
SELECT DISTINCT Category
FROM MonitoringJob
ORDER BY Category DESC
If you want to sort records based on CreationDate field then this field must be in the select statement:
SELECT DISTINCT Category, creationDate
FROM MonitoringJob
ORDER BY CreationDate DESC
You can use CTE:
WITH DistinctMonitoringJob AS (
SELECT DISTINCT Category Distinct_Category FROM MonitoringJob
)
SELECT Distinct_Category
FROM DistinctMonitoringJob
ORDER BY Distinct_Category DESC
By subquery, it should work:
SELECT distinct(Category) from MonitoringJob where Category in(select Category from MonitoringJob order by CreationDate desc);
We can do this with select sub query
Here is the the query:
SELECT * FROM (
SELECT DISTINCT Category FROM MonitoringJob
) AS Tbl
ORDER BY Tbl.CreationDate DESC
Try next, but it's not useful for huge data...
SELECT DISTINCT Cat FROM (
SELECT Category as Cat FROM MonitoringJob ORDER BY CreationDate DESC
);
It can be done using inner query Like this
$query = "SELECT *
FROM (SELECT Category
FROM currency_rates
ORDER BY id DESC) as rows
GROUP BY currency";
SELECT DISTINCT Category FROM MonitoringJob ORDER BY Category ASC