Sybase Select WHERE IN given order - sql

Is there a way to keep the order when using SELECT WHERE IN() in Sybase
There are two examples in mysql:
SELECT * FROM table WHERE id IN (118,17,113,23,72)
ORDER BY FIELD(id,118,17,113,23,72)
SELECT * FROM table WHERE id IN (118,17,113,23,72)
ORDER BY FIND_IN_SET(id, '118,17,113,23,72')
I need it in Sybase Ase.

You could break down the argument list with a case statement the explicitly assigns an ascending counter to the arguments and order according to that:
SELECT *
FROM sometable
WHERE id IN (118,17,113,23,72)
ORDER BY CASE id WHEN 118 THEN 1
WHEN 17 THEN 2
WHEN 113 THEN 3
WHEN 23 THEN 4
WHEN 72 THEN 5
END ASC
It's clunky as hell, but it should work.

Related

How to select only one entry based on each parameter [duplicate]

This question already has answers here:
Retrieving last record in each group from database - SQL Server 2005/2008
(2 answers)
Closed 7 years ago.
This has probably been asked before, but I have no idea on how to find it in the first place.
In the following query (with respective returned values):
select * from tbChapter where idLesson in(12, 13)
-- Result --
id idLesson name sequence
52 12 Intro 1
53 12 Chapter One 2
54 12 Chapter Two 3
55 13 Intro 1
56 13 Chapter One 2
57 13 Chapter Two 3
58 13 Chapter Three 4
I want to get only the last entry for each idLesson, for example:
-- Expected result --
id idLesson name sequence
54 12 Chapter Two 3
58 13 Chapter Three 4
How can I proceed?
Ps: I'l actually replace where idLesson in(12, 13) with subquery that will return dozens of idLesson values.
Try this:
select * from tbChapter where id in
(select MAX(id) from tbChapter group by idLesson)
Try this:
select *
from tbChapter as a
where sequence = (select max(sequence)
from tbChapter as b
where a.id_lesson = b.id_lesson)
The canonical way is to use window functions. Here is an example:
select c.*
from (select c.*, max(sequence) over (partition by idLesson) as maxs
from tblChapter c
) c
where sequence = maxs;
A more creative way that might perform better under some circumstances is to use cross apply:
select c.*
from (select distinct idLesson from tblChapter) l cross apply
(select top 1 c*
from tblChapter c
where c.idLesson = l.idLesson
order by sequence desc
) c;
Note that the first subquery can be replaced by a table that has all the lessons, with one per row.
SELECT
Max(id),
idlesson,
name,
Max(sequence)
FROM
tbChapter
WHERE
idLesson in(12, 13)
GROUP BY
idlesson,
name

counting subquery in SQL

I have the following query to count how many times each process_track_id occurs in a table:
SELECT
a.process_track_id,
COUNT(1) AS 'num'
FROM
transreport.process_name a
GROUP BY
a.process_track_id
This returns the following results:
process_track_id | num
1 14
2 44
3 16
5 8
6 18
7 17
8 14
This is great. Now is the part where I am stuck. I would like to get the following table:
num count
8 1
14 2
16 1
17 1
18 1
44 1
Where num are the distinct counts from the first table, and count is how many times that frequency occurs.
Here is what I have tried (it's a subquery, but I'm not sold on the method) and I haven't been able to get it to work just yet. I'm new to SQL and I think I'm missing out on some some key aspects of the syntax.
SELECT
X.id_count,
count(1) as 'num_count'
FROM
(SELECT
a.process_track_id,
COUNT(1) AS 'id_count'
FROM
transreport.process_name a
GROUP BY
a.process_track_id
--COUNT(1) AS 'id_count'
) X;
Any ideas?
It's probably good to keep in mind that this may have to be run on a database with at least 1 million records, and I don't have the ability to create a new table in the process.
Thanks!
Here's the subquery method you were driving at:
SELECT id_count, COUNT(*) AS 'num_count'
FROM (SELECT a.process_track_id
,COUNT(*) AS 'id_count'
FROM transreport.process_name a
GROUP BY a.process_track_id
)sub
GROUP BY id_count
Not sure there's a better method as the aggregation needs to run once anyway.
Try this
SELECT x.num, COUNT(*) AS COUNT
FROM (
SELECT
a.process_track_id, -- <--- You may removed this column
COUNT(*) AS 'num'
FROM
transreport.process_name a
GROUP BY
a.process_track_id
) X
GROUP BY X.num

SQL: create sequential list of numbers from various starting points

I'm stuck on this SQL problem.
I have a column that is a list of starting points (prevdoc), and anther column that lists how many sequential numbers I need after the starting point (exdiff).
For example, here are the first several rows:
prevdoc | exdiff
----------------
1 | 3
21 | 2
126 | 2
So I need an output to look something like:
2
3
4
22
23
127
128
I'm lost as to where even to start. Can anyone advise me on the SQL code for this solution?
Thanks!
;with a as
(
select prevdoc + 1 col, exdiff
from <table> where exdiff > 0
union all
select col + 1, exdiff - 1
from a
where exdiff > 1
)
select col
If your exdiff is going to be a small number, you can make up a virtual table of numbers using SELECT..UNION ALL as shown here and join to it:
select prevdoc+number
from doc
join (select 1 number union all
select 2 union all
select 3 union all
select 4 union all
select 5) x on x.number <= doc.exdiff
order by 1;
I have provided for 5 but you can expand as required. You haven't specified your DBMS, but in each one there will be a source of sequential numbers, for example in SQL Server, you could use:
select prevdoc+number
from doc
join master..spt_values v on
v.number <= doc.exdiff and
v.number >= 1 and
v.type = 'p'
order by 1;
The master..spt_values table contains numbers between 0-2047 (when filtered by type='p').
If the numbers are not too large, then you can use the following trick in most databases:
select t.exdiff + seqnum
from t join
(select row_number() over (order by column_name) as seqnum
from INFORMATION_SCHEMA.columns
) nums
on t.exdiff <= seqnum
The use of INFORMATION_SCHEMA columns in the subquery is arbitrary. The only purpose is to generate a sequence of numbers at least as long as the maximum exdiff number.
This approach will work in any database that supports the ranking functions. Most databases have a database-specific way of generating a sequence (such as recursie CTEs in SQL Server and CONNECT BY in Oracle).

How to delete all duplicate records from SQL Table?

Hello I have table name FriendsData that contains duplicate records as shown below
fID UserID FriendsID IsSpecial CreatedBy
-----------------------------------------------------------------
1 10 11 FALSE 1
2 11 5 FALSE 1
3 10 11 FALSE 1
4 5 25 FALSE 1
5 10 11 FALSE 1
6 12 11 FALSE 1
7 11 5 FALSE 1
8 10 11 FALSE 1
9 12 11 FALSE 1
I want to remove duplicate combinations rows using MS SQL?
Remove latest duplicate records from MS SQL FriendsData table.
here I attached image which highlights duplicate column combinations.
How I can removed all duplicate combinations from SQL table?
Try this
DELETE
FROM FriendsData
WHERE fID NOT IN
(
SELECT MIN(fID)
FROM FriendsData
GROUP BY UserID, FriendsID)
See here
Or here is more ways to do what you want
Hope this helps
It seems counter-intuitive, but you can delete from a common table expression (under certain circumstances). So, I'd do it like so:
with cte as (
select *,
row_number() over (partition by userid, friendsid order by fid) as [rn]
from FriendsData
)
delete cte where [rn] <> 1
This will keep the record with the lowest fid. If you want something else, change the order by clause in the over clause.
If it's an option, put a uniqueness constraint on the table so you don't have to keep doing this. It doesn't help to bail out a boat if you still have a leak!
I don't know if the syntax is correct for MS-SQL, but in MySQL, the query would look like:
DELETE FROM FriendsData WHERE fID
NOT IN ( SELECT fID FROM FriendsData
GROUP BY UserID, FriendsUserID, IsSpecial, CreatedBy)
In the GROUP BY clause you put the columns you need to be identical in order to consider two records duplicate
Try this query,
select * from FriendsData f1, FriendsData f2
Where f1.fID=f2.fID and f1.UserID =f2.UserID and f1.FriendsID =f2.FriendsID
If it returns you the duplicate rows, then replace Select * by "Delete"
that will solve your problem
Works in Postgres:
DELETE from "FriendsData" where "fID" in
(SELECT "fID" from
(SELECT *, ROW_NUMBER() OVER(PARTITION BY "UserID", "FriendsID" ORDER BY "fID") as rn
FROM "FriendsData") as inner1
WHERE rn > 1);

sql query adding column values

I want to add two columns values of my table and sort it in descending order. E.g:
int_id int_test_one int_test_2
1 25 13
2 12 45
3 25 15
Considering the table above, I want a SQL query which give me the result like below:
int_id sum(int_test_one,int_test_two)
2 57
3 40
1 38
Is there any sql query to do this?
There is not built in function for this kind of horizontal aggregation, you can just do...
SELECT INT_ID, INT_TEST_ONE + INT_TEST_TWO AS SUM FROM TABLE
Did you try what you describe? This works:
SELECT int_id , ( int_test_one + int_test_two ) as s FROM mytable ORDER BY s DESC
You can ommit the "as" keyword if you want.
Try this
SELECT
int_id,
(int_test_one + int_test_two) AS [Total]
FROM
mytable
ORDER BY
[Total] DESC