SQL Server Adding Order with CTE - sql

I want to achieve something easy in an while loop but it's too slow to run so I'm sure I can do this with an CTE table but I don't know how..
I have two table with a join one to many and i'm trying to put an order in my detail here's my data:
for each IDRV you have many IDRVOBJET. I want to put an order number 1 to n for each IDRVOBJET in IDRV. I don't know if i'm clear but here's what I should have as result:
Thanks for taking the time to help me!
EDIT
Here's the formated text:
IDRV IDRVOBJET ORDER
12700 76357 1
12700 76358 2
12701 76363 1
12701 76364 2
12701 76365 3
12702 76359 1
12702 76360 2
12703 76120 1
12703 76121 2
12703 76122 3
12705 19375 1
12705 19376 2
12706 19410 1
12707 19408 1
12707 19409 2
12709 22473 1
12709 22474 2
12711 40352 1
12711 40353 1

Just use a window function.
SELECT
IDRV,
IDRVOBJECT,
ROW_NUMBER() OVER (PARTITION BY IDRV ORDER BY IDRVOBJECT) as ORDRE
FROM YourTable

You can use row_number and partition by
select *, Ordr = Row_Number() over (partition by IDRV order by IDRVOBJET) from your table

SELECT IDRV,IDRVOBJECT,Row_Number()Over(Partition by IDRV Order by IDRVOBJECT) AS ORDRE
FROM <yourtable>

Related

SQL Compare Rows With Duplicate IDs and Return One With Lowest Sequence Number

Reaching out for help. I've seen plenty of answers on how to use DUPLICATE, but not quite how I need it. Let's say I have the result of query that looks like the following.
query result
Incident_No Open_Approval_Step Approval_ID
------------- -------------------- -------------------
1 3 Tech
1 4 Cust_Serv
2 1 Incident_Recorder
2 2 Estimation
2 3 Tech
3 4 Cust_Serv
3 5 Mgmt
3 6 Closure
And I need one row for each incident number with the smallest numbered approval step. So the result should look like this.
filtered query result
Incident_No Open_Approval_Step Approval_ID
------------- -------------------- -------------------
1 3 Tech
2 1 Incident_Recorder
3 4 Cust_Serv
Edit This is what I came up with in the end
SELECT DISTINCT
MIN(OPEN_APPROVAL_STEP) OVER(PARTITION BY INCIDENT_NO ORDER BY OPEN_APPROVAL_STEP ASC) AS CUR_APP_STEP,
INCIDENT_NO
FROM T
You can use row_number():
select *
from (
select
t.*,
row_number() over(partition by incident_no order by open_approval_step) rn
from mytable t
) t
where rn = 1
With just one extra column appart from the incident number and approval step, another option is aggregation and Oracle's keep syntax:
select
incident_no,
min(open_approval_step) open_approval_step,
min(approval_id) keep(dense_rank first order by open_approval_step) approval_id
from mytable
group by incident_no
If you have just three columns, you can easily use aggregation:
select incident_no, min(open_approval_step),
min(approval_id) keep (dense_rank first order by open_approval_step)
from t
group by incident_no;

Querying Data Backward in ORACLE SQL

I have a simple question regarding oracle sql. So i have this table
WEEKNUM DATA
1 10
2 4
3 6
4 7
So i want to make a view that shows like this,
WEEKNUM DATA ACCUM_DATE
1 10 10
2 4 14
3 6 20
4 7 27
I spend hours on this simple one but couldnt get any luck
thanks a lot
SELECT weeknum,
data,
sum(data) over (order by weeknum) accum_data
FROM your_table_name
should work. I'm using the sum analytic function here and assuming that you want to start with the smallest weeknum value and keep increasing the running total as the weeknum values increase. I'm also assuming that you never want to reset the accumulated sum. If you're trying to do something like generating an accumulated sum that restarts each year, you'd want to add a partition by to the analytic function.
You could use a Cross JOin in this case
Query:
select
A.WEEKNUM
, A.DATA
, SUM(B.DATA) DA
from table1 A
cross join table1 B
WHERE A.WEEKNUM>=B.WeekNUM
GROUP BY A.WEEKNUM
, A.DATA
order by A.WEEKNUM
Result:
WEEKNUM DATA DA
1 10 10
2 4 14
3 6 20
4 7 27
Thanks guys but i just found out this method works perfectly,
OVER (ORDER BY WEEKNUM ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS CUMULATIVE_WEIGHT
Or use a sub-select to calculate:
select WEEKNUM, DATA, (select sum(DATA) from tablename t2
where t2.weeknum <= t1.weeknum) as ACCUM_DATE
from tablename t1

In SQL, I need to generate a ranking (1st, 2nd, 3rd) column, getting stuck on "ties"

I have a query that calculates points based on multiple criteria, and then orders the result set based on those points.
SELECT * FROM (
SELECT
dbo.afunctionthatcalculates(Something, Something) AS Points1
,dbo.anotherone(Something, Something) AS Points2
,dbo.anotherone(Something, Something) AS Points3
,[TotalPoints] = dbo.function(something) + dbo.function(something)
) AS MyData
ORDER BY MyData.TotalPoints
So my first stab at adding placement, rankings.. was this:
SELECT ROW_NUMBER() OVER(MyData.TotalPoints) AS Ranking, * FROM (
SELECT same as above
) AS MyData
ORDER BY MyData.TotalPoints
This adds the Rankings column, but doesn't work when the points are tied.
Rank | TotalPoints
--------------------
1 100
2 90
3 90
4 80
Should be:
Rank | TotalPoints
--------------------
1 100
2 90
2 90
3 80
Not really sure about how to resolve this.
Thank you for your help.
You should use the DENSE_RANK() function which takes the ties into account, as described here: http://msdn.microsoft.com/en-us/library/ms173825.aspx
DENSE_RANK() instead of ROW_NUMBER()

SQL - Search a table for all instances where a value is repeated

I'm looking to find a way to search a table for duplicate values and return those duplicates (or even just one of the set of duplicates) as the result set.
For instance, let's say I have these data:
uid | semi-unique id
1 | 12345
2 | 21345
3 | 54321
4 | 41235
5 | 12345
6 | 21345
I need to return either:
12345
12345
21345
21345
Or:
12345
21345
I've tried googling around and keep coming up short. Any help please?
To get each row, you can use window functions:
select t.*
from (select t.*, count(*) over (partition by [semi-unique id]) as totcnt
from t
) t
where totcnt > 1
To get just one instance, try this:
select t.*
from (select t.*, count(*) over (partition by [semi-unique id]) as totcnt,
row_number() over (partition by [semi-unique id] order by (select NULL)
) as seqnum
from t
) t
where totcnt > 1 and seqnum = 1
The advantage of this approach is that you get all the columns, instead of just the id (if that helps).
Sorry, I was short on time earlier so I couldn't explain my answer. The first query groups the semi_unique_ids that are the same and only returns the ones that have a duplicate.
SELECT semi_unique_id
FROM your_table
GROUP BY semi_unique_id
HAVING COUNT(semi_unique_id) > 1
If you wanted to get the uid in the query too you can easily add it like so.
SELECT uid,
semi_unique_uid
FROM your_table
GROUP BY
semi_unique_id,
uid
HAVING COUNT(semi_unique_id) > 1
Lastly if you would like to get an idea of how many duplicates per row returned you would do the following.
SELECT uid,
semi_unique_uid,
COUNT(semi_unique_uid) AS unique_id_count
FROM your_table
GROUP BY
semi_unique_id,
uid
HAVING COUNT(semi_unique_id) > 1
SELECT t.semi_unique_id AS i
FROM TABLE t
GROUP BY
t.semi_unique_id
HAVING (COUNT(t.semi_unique_id) > 1)
Try this for sql-server

SQL: how do write the ORDER BY based on value within a group?

I have a table
project issues updated
1 1 2009-09-03
1 2 2009-09-08
2 1 2009-09-12
2 2 2009-09-01
and I would like to sort so that the projects are sorted in descending order so that the project with the latest updated issue is first etc., but all issues of a project are kept together and the issues are in ascending order within the project based on issue number
the result should be:
project issues updated
2 1 2009-09-12
2 2 2009-09-01
1 1 2009-09-03
1 2 2009-09-08
Something like this should do the job:
SELECT mt.*
FROM mytable mt
JOIN (SELECT MAX(updated) AS LastUpdated, project
FROM mytable GROUP BY project) lu ON lu.project = mt.project
ORDER BY lu.LastUpdated DESC, mt.Issues
Oops, I just saw the MySQL tag. I don't know if this solution will work in MySQL
I think this would work (sorry, no mysql at hand, so I just tested on sqlite...):
select t.project, t.issues, t.updated from t
join (select project, max(updated) as dat
from t group by project) as t1
on (t.project = t1.project)
order by t1.dat desc, t.issues asc
SELECT p.project, p.issues, p.updated, max(r.updated)
FROM table p INNER JOIN table r ON r.project=p.project
GROUP BY p.project, p.issues, p.updated
ORDER BY 4 DESC, p.project, p.issues
I've tried an equivalent query in mysql & it looks like it works the way you want it to.