Why doesn't SQL DISTINCT work with ORDER BY CAST? - sql

Including DISTINCT to an SQL query that also uses ORDER BY CAST(thecolumn AS int) as shown here seems to remove that sorting functionality.
Any reason these cant work together?
(Using sqlite with the C api)
Thanks.
EDIT:
Started with -
sprintf(sql, "SELECT DISTINCT rowX FROM TableX Order By Cast(rowX As int) LIMIT 150 OFFSET %s;", Offset);
rowX is Type CHAR(5)
NOW:
sprintf(sql, "Select rowX FROM(Select Distinct rowX From TableX)t Order By Cast(rowX As int) LIMIT 150 OFFSET %s;", Offset);

I used the following with sqlite, and sorting worked fine:
Select Distinct thecolumn
From your_table
Order By Cast(thecolumn As int)
Have you tried putting the DISTINCT into a sub-query?
Select thecolumn
From
(
Select Distinct thecolumn
From your_table
) t
Order By Cast(thecolumn As int)
I would expect it to work that way.
One more way:
Select thecolumn
From
(
Select Distinct Cast(thecolumn As int) As thecolumn
From your_table
) t
Order By thecolumn

This is way super late, but the order by has to match the select list exactly so:
select distinct cast(column as int)
from table
order by cast(column as int)

Related

How do I sample the number of records in another table?

I have code where I'm sampling 50,000 random records. I.e.,
SELECT * FROM Table1
SAMPLE 50000;
That works. However, what I really want to do is sample the number of records that are in a different table. I.e.,
SELECT * FROM Table1
SAMPLE count(*) FROM Table2;
I get an error. What am I doing wrong?
This is not randomized like sample, so bear that in mind. But there also won't be an obvious pattern, I believe it's determined by disk location (don't quote me on that).
SELECT *
FROM Table1
QUALIFY ROW_NUMBER() OVER
( PARTITION BY 1
ORDER BY 1
) <=
( SELECT COUNT(*)
FROM Table2
);
Better way
SELECT TMP.* -- Or list the columns you want with "rnd"
FROM ( SELECT RANDOM(-10000000,10000000) rnd,
T1.*
FROM Table1 T1
) TMP
QUALIFY ROW_NUMBER() OVER
( ORDER BY rnd
) <=
( SELECT COUNT(*)
FROM Table2
);
SELECT TOP 50000 * FROM Table1 ORDER BY NEWID()

Need to perform ORDER by Twice

I want to sort according to date first and then if date is similar then according to id..How to do that in Informix/HSQL query?
SELECT FIELD1, FIELD2 FROM TABLE ORDER BY FIELD1 ASC, FIELD2 ASC
A good tutorial on this SQL ORDER BY
This should work:
SELECT * FROM Table
ORDER BY date, id;
Does
[rest of query] order by date, id
work?
Try this(adjusted to your needs):
SELECT * FROM table ORDER BY datecol ASC, id ASC
select * from (select * from tablename order by col1) AS T order by col2
(It's necessary to give an alias to the virtual table, hence "AS T")
select * from (select * from tablename order by col1) AS T order by col2
This works but is redundant and obtuse. Note the subquery (on "col1") becomes the secondary sort; the primary sort is the encompassing query. Some environments may require the "as T" aliasing of the subquery, but not all.
select * from tablename order by col2, col1
This does the same thing as above, with simple clarity
Or for a more realistic example:
select * from customers order by lastname, firstname

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;

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

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