I have table with invoice in Oracle database. I will need to select invoice_id column from invoice in 3 column ordered by data_creation.
Result should be like under
invoie_id invoie_id invoie_id
1 2 3
4 5 6
...
You can do this by using rownum & inline view of the same column to split them in columns. Then you have to make join. Your query will be like
select g.empno, f.empno from (select e.empno from emp e
where rownum < 3 or rownum >2)f, emp g
where g.empno = f.empno
and rownum < 3
This is just a direction for you not the exact answer. You can create your logic from here.
Ok i found by myself
select *
from (
SELECT invoice_id,
LEAD (invoice_id,1) OVER (ORDER BY invoice_date) AS next_invoice ,
LEAD (invoice_id,2) OVER (ORDER BY invoice_date) AS next_invoice2
FROM invoice ORDER BY invoice_date)
where mod(rownum,3) = 0
Related
In my last post (Below link), I've tried to use the ROW_NUMBER ORDER BY and finally got the required solution. See the following link:
Get Wages Yearly Increment Column Wise Using Sql
Now I am trying to use the following query in Sql server 2000, just for demonstration purpose. I know, ROW_NUMBER ORDER BY can't be used in it. And after some googling, tried to use the following for Sql server 2000: (1st query)
SELECT k.ID, k.[Name], m.Amt,
(SELECT COUNT(*) FROM EmpIncrement l WHERE l.EmpID <= m.EmpID) as RowNum
FROM EmpIncrement m
JOIN Employee k ON m.EmpID = k.ID
And I got this output:
ID Name Amt RowNum
1 John 2000 2
2 Jack 8000 4
1 John 1000 2
2 Jack 4000 4
Similarly when I use the following with ROW_NUMBER ORDER BY, then it shows different output: (2nd query)
SELECT k.ID, k.Name, m.Amt,
ROW_NUMBER() OVER (PARTITION BY EmpID ORDER BY DATEPART(yy,IncrementDate)) as RowNum
FROM EmpIncrement m
JOIN Employee k ON k.ID = m.EmpID
Output:
ID Name Amt RowNum
1 John 1000 1
2 John 2000 2
1 Jack 4000 1
2 Jack 8000 2
So it's noticed that the grouping for the employee ids (RowNum) are different in both the queries where the output of the second query is correct. I would like to know the difference of both the queries output and if the 1st query is equivalent to ROW_NUMBER ORDER BY. Thanks.
Note: I didn't include the table structure and sample data here again. Never mind - You can see the earlier post for that.
To recreate the partition by EmpId, your subquery should have l.EmpId = m.Empid. You really need a unique column or set of columns to unique identify a row for this version to work properly. In an attempt based on the given data, if EmpId, Amt are a unique pair you can use and l.Amt < m.Amt. If you have a surrogateid on the table, that would be better instead of Amt.
select
k.id
, k.[Name]
, m.Amt
, ( select count(*)
from EmpIncrement l
where l.Empid = m.Empid
and l.Amt <= m.Amt
) as RowNum
from EmpIncrement m
inner join Employee k
on m.Empid = k.id
If you have no set of columns to uniquely identify and order the rows, you can use a temporary table with an identity() column.
create table #temp (tmpid int identity(1,1) not null, id int, [Name] varchar(32), Amt int);
insert into #temp (id, [Name], Amt);
select
k.id
, k.[Name]
, m.Amt
from EmpIncrement m
inner join Employee k
on m.Empid = k.id;
select
t.id
, t.[Name]
, t.Amt
, ( select count(*)
from #Temp i
where i.Empid = t.Empid
and i.tmpId <= t.tmpId
) as RowNum
from #temp t
I have a SQL table Customer with the following columns:
Customer_ID, Actioncode
I have another table with 1000+ actioncodes. Now I want to update the records in the Customer table with a unique code from the actioncode table.
I use this select statement at the moment:
update t
set t.actiecode = (select top 1 actiecode from data_mgl_campagnemails_codes)
from data_mgl_campagnemails_transfer t;
The result is that all records are updated with the same actiecode. The top 1 is responsible for that. When I remove that I got an error:
Subquery returned more than 1 value
This seems logical. How can I do this without using a cursor?
There is no relationship between the Customer and Code table.
Table structure:
data_mgl_campagnemails_transfer
id customer_id actioncode actioncode_id
1 1 - -
2 3 - -
3 4 - -
data_mgl_campagnemails_codes
id actioncode active
1 TTTT
2 RRRR
3 VVVV
4 RRRW
The result should be:
data_mgl_campagnemails_transfer
id customer_id actioncode actioncode_id
1 1 TTTT 1
2 3 RRRR 2
3 4 VVVV 3
data_mgl_campagnemails_codes
id actioncode active
1 TTTT YES
2 RRRR YES
3 VVVV YES
4 RRRW
This can be a bit tricky using a single statement, because SQL Server likes to optimize things. So the obvious:
update t
set t.actiecode = (select top 1 actiecode
from data_mgl_campagnemails_codes
order by newid()
)
from data_mgl_campagnemails_transfer t;
Also doesn't work. One method is to enumerate things and use a join or correlated subquery:
with t as (
select t.*, row_number() over (order by newid()) as seqnum
from data_mgl_campagnemails_transfer t
),
a as (
select a.*, row_number() over (order by newid()) as seqnum
from data_mgl_campagnemails_codes a
)
update t
set t.actiecode = (select top 1 actiecode from a)
from t join
a
on t.seqnum = a.seqnum;
Another way is to "trick" SQL Server into running the correlated subquery more than once. I think something like this:
update t
set t.actiecode = (select top 1 actiecode
from data_mgl_campagnemails_codes
where t.CustomerId is not null -- references the outer table but really does nothing
order by newid()
)
from data_mgl_campagnemails_transfer t;
I have a query thats displaying result, but i want 3 highest values only in Ascending order from this query
select (sum(l.quantity*l.rate-l.recieved)+first(c.openbal)) as total from customer c RIGHT
JOIN ledger l ON l.refno = c.refno group by l.refno
You can use the TOP key word for it with ORDER BY Cluase
like
Select TOP 1 * from TABLE //Will return top most row
Select TOP 2 * from TABLE //Will return top 2 rows
Select TOP 3 * from TABLE //Will return top 3 rows
Your query should be
select TOP 3 (sum(l.quantity*l.rate-l.recieved)+first(c.openbal)) as total from customer
c RIGHT JOIN ledger l ON l.refno = c.refno group by l.refno ORDER BY
(sum(l.quantity*l.rate-l.recieved)+first(c.openbal)) DESC
try something like this
SELECT *
FROM (
SELECT SUM(Amount) as total, RANK() OVER (ORDER BY SUM(Amount) Desc) rankME
FROM tmp_Agents
GROUP BY AgentName
) x
WHERE rankME <= 3
try this
select TOP 3 (sum(l.quantity*l.rate-l.recieved)+first(c.openbal)) as total from customer c
RIGHT JOIN ledger l ON l.refno = c.refno group by l.refno ORDER BY total DESC
I have a table of election results for multiple nominees and polls. I need to determine which nominee had the most votes for each poll.
Here's a sample of the data in the table:
PollID NomineeID Votes
1 1 108
1 2 145
1 3 4
2 1 10
2 2 41
2 3 0
I'd appreciate any suggestions or help anyone can offer me.
This will match the highest, and will also bring back ties.
select sd.*
from sampleData sd
inner join (
select PollID, max(votes) as MaxVotes
from sampleData
group by PollID
) x on
sd.PollID = x.PollID and
sd.Votes = x.MaxVotes
SELECT
t.NomineeID,
t.PollID
FROM
( SELECT
NomineeID,
PollID,
RANK() OVER (PARTITION BY i.PollID ORDER BY i.Votes DESC) AS Rank
FROM SampleData i) t
WHERE
t.Rank = 1
SELECT PollID, NomineeID, Votes
FROM
table AS ABB2
JOIN
(SELECT PollID, MAX(Votes) AS most_votes
FROM table) AS ABB1 ON ABB1.PollID = ABB2.PollID AND ABB1.most_votes = ABB2.Votes
Please note, if you have 2 nominees with the same number of most votes for the same poll, they'll both be pulled using this query
select Pollid, Nomineeid, Votes from Poll_table
where Votes in (
select max(Votes) from Poll_table
group by Pollid
);
I have a performance issue when selecting data in my project.
There is a table with 3 columns: "id","time" and "group"
The ids are just unique ids as usual.
The time is the creation date of the entry.
The group is there to cummulate certain entries together.
So the table data may look like this:
ID | TIME | GROUP
------------------------
1 | 20090805 | A
2 | 20090804 | A
3 | 20090804 | B
4 | 20090805 | B
5 | 20090803 | A
6 | 20090802 | B
...and so on.
The task is now to select the "current" entries (their ids) in each group for a given date. That is, for each group find the most recent entry for a given date.
Following preconditions apply:
I do not know the different groups in advance - there may be many different ones changing over time
The selection date may lie "in between" the dates of the entries in the table. Then I have to find the closest one in each group. That is, TIME is less than the selection date but the maximum of those to which this rule applies in a group.
What I currently do is a multi-step process which I would like to change into single SELECT statement:
SELECT DISTINCT group FROM table to find the available groups
For each group found in 1), SELECT * FROM table WHERE time<selectionDate AND group=loop ORDER BY time DESC
Take the first row of each result found in 2)
Obviously this is not optimal.
So I would be very happy if some more experienced SQL expert could help me to find a solution to put these steps in a single statement.
Thank you!
The following will work on SQL Server 2005+ and Oracle 9i+:
WITH groups AS (
SELECT t.group,
MAX(t.time) 'maxtime'
FROM TABLE t
GROUP BY t.group)
SELECT t.id,
t.time,
t.group
FROM TABLE t
JOIN groups g ON g.group = t.group AND g.maxtime = t.time
Any database should support:
SELECT t.id,
t.time,
t.group
FROM TABLE t
JOIN (SELECT t.group,
MAX(t.time) 'maxtime'
FROM TABLE t
GROUP BY t.group) g ON g.group = t.group AND g.maxtime = t.time
Here's how I would do it in SQL Server:
SELECT * FROM table WHERE id in
(SELECT top 1 id FROM table WHERE time<selectionDate GROUP BY [group] ORDER BY [time])
The solution will vary by database server, since the syntax for TOP queries varies. Basically you are looking for a "top n per group" query, so you can Google that if you want.
Here is a solution in SQL Server. The following will return the top 10 players who hit the most home runs per year since 1990. The key is to calculate the "Home Run Rank" of each player for each year.
select
HRRanks.*
from
(
Select
b.yearID, b.PlayerID, sum(b.Hr) as TotalHR,
rank() over (partition by b.yearID order by sum(b.hr) desc) as HR_Rank
from
Batting b
where
b.yearID > 1990
group by
b.yearID, b.playerID
)
HRRanks
where
HRRanks.HR_Rank <= 10
Here is a solution in Oracle (Top Salespeople per Department)
SELECT deptno, avg_sal
FROM(
SELECT deptno, AVG(sal) avg_sal
GROUP BY deptno
ORDER BY AVG(sal) DESC
)
WHERE ROWNUM <= 10;
Or using analytic functions:
SELECT deptno, avg_sal
FROM (
SELECT deptno, avg_sal, RANK() OVER (ORDER BY sal DESC) rank
FROM
(
SELECT deptno, AVG(sal) avg_sal
FROM emp
GROUP BY deptno
)
)
WHERE rank <= 10;
Or same again, but using DENSE_RANK() instead of RANK()
select * from TABLE where (GROUP, TIME) in (
select GROUP, max(TIME) from things
where TIME >= 20090804
group by GROUP
)
Tested with MySQL (but I had to change the table and column names because they are keywords).
SELECT *
FROM TABB T1
QUALIFY ROW_NUMBER() OVER ( PARTITION BY GROUPP,TIMEE order by id desc )=1