Having the following dataset. I need some help with a sql statement that would give me the latest row based on PING_DATE with unique PING_DESTINATION and PING_SOURCE with added column with the AVG of PING_AVG for all rows within the last 10 minutes.
PING_DATE | PACKET_LOSS | PING_MIN | PING_AVG | PING_MAX | PING_SOURCE | PING_DESTINATION
-------------------------------------------------------------------------------------------------------
5/5/2015 12:58:18 PM | 0 | 68 | 68 | 72 | site1 | orange15
5/5/2015 12:58:43 PM | 0 | 68 | 71 | 76 | site1 | orange15
5/5/2015 12:59:11 PM | 0 | 68 | 68 | 72 | site1 | pear11
5/5/2015 1:09:47 PM | 0 | 68 | 70 | 76 | site1 | pear11
5/5/2015 1:43:59 PM | 0 | 68 | 69 | 72 | site1 | pear11
5/5/2015 1:45:41 PM | 0 | 68 | 69 | 72 | site1 | pear11
5/5/2015 2:03:43 PM | 0 | 68 | 68 | 72 | site1 | pear11
5/5/2015 3:01:53 PM | 0 | 68 | 68 | 72 | site1 | pear11
5/5/2015 3:02:05 PM | 0 | 68 | 69 | 72 | site1 | pear11
5/5/2015 3:00:59 PM | 20 | 68 | 68 | 68 | site1 | pear11
5/5/2015 3:01:07 PM | 0 | 68 | 68 | 72 | site1 | pear11
5/5/2015 3:01:14 PM | 0 | 68 | 70 | 72 | site1 | pear11
5/5/2015 12:46:55 PM | 3 | 3 | 3 | 3 | site1 | lemon1
Query Result:
PING_DATE | PACKET_LOSS | PING_MIN | PING_AVG | PING_MAX | PING_SOURCE | PING_DESTINATION | 10minavg
------------------------------------------------------------------------------------------------------------------
5/5/2015 12:58:43 PM | 0 | 68 | 71 | 76 | site1 | orange15 | 71
5/5/2015 3:01:14 PM | 0 | 68 | 70 | 72 | site1 | pear11 | 65
5/5/2015 12:46:55 PM | 3 | 3 | 3 | 3 | site1 | lemon1 | 3
For "last 10 minutes average" being "last 10 minutes in each group" this is the query you are looking for:
with xyz as (
select X.*,
row_number() over (
partition by ping_destination, ping_source
order by ping_date desc
) as latest_row#,
avg(ping_avg) over (
partition by ping_destination, ping_source
order by ping_date asc
range between
interval '10' minute preceding
and current row
) as the_10_min_avg
from ping_table X
)
select *
from xyz
where latest_row# = 1
;
For "last 10 minutes average" being "from 10 minutes ago until now" this is the query you are looking for:
with xyz as (
select X.*,
row_number() over (
partition by ping_destination, ping_source
order by ping_date desc
) as latest_row#,
avg(ping_avg) over (
partition by ping_destination, ping_source
) as the_10_min_avg
from ping_table X
where X.ping_date >= systimestamp - interval '10' minute
)
select *
from xyz
where latest_row# = 1
;
Something like this:
SELECT DISTINCT ping_source,
first_value(ping_date) over (partition by ping_source order by ping_date desc),
first_value(packet_loss) over (partition by ping_source order by ping_date desc)
-- ...
FROM data
CROSS JOIN
select avg(ping_avg) from data
where (sysdate - ping_date) * 24 * 60 < 10;
Here is a straight forward query based on the question.
Edited based on the sample output. For last 10 minutes from now, use systemtimestamp instead of i.latest_ping in the snippet "(i.latest_ping - interval '10' minute)". Use i.latest_ping for last 10 minutes from max_ping_time for that source-dest pair.
select
o.*,
(select avg(ping_avg) from ping_info a
where a.ping_source = i.ping_source
and a.ping_dest = i.ping_dest
and a.ping_date >= (systemtimestamp - interval '10' minute)
) last_10min_avg
from ping_info o,
(select ping_source, ping_dest, max(ping_date) latest_ping
from ping_info
group by ping_source, ping_dest) i
where o.ping_source = i.ping_source
and o.ping_dest = i.ping_dest
and o.ping_date = i.latest_ping;
Related
I have the current table of data...
| LoanRollupID | NewLoanID | PreviousLoanID |
|--------------|-----------|----------------|
| 11 | 76 | 44 |
| 12 | 80 | 75 |
| 13 | 83 | 82 |
| 14 | 84 | 83 |
| 15 | 86 | 85 |
| 16 | 87 | 54 |
| 17 | 88 | 87 |
| 18 | 90 | 48 |
| 19 | 91 | 34 |
| 20 | 93 | 41 |
| 21 | 94 | 76 |
| 22 | 95 | 90 |
| 23 | 96 | 94 |
| 24 | 100 | 92 |
| 25 | 101 | 99 |
| 26 | 102 | 98 |
| 27 | 103 | 101 |
| 28 | 104 | 81 |
| 29 | 105 | 80 |
| 30 | 107 | 52 |
| 31 | 110 | 108 |
| 1029 | 1105 | 103 |
| 1030 | 1106 | 104 |
| 1031 | 1108 | 1106 |
| 1032 | 1109 | 73 |
I'm trying to jump in at NewLoanID 1108 and see how it has evolved from previous Loans. e.g 1108 came from 1106, which came from 104, which came from 81, etc.
When I run this query:
WITH OldLoans (PreviousLoanID, NewLoanID, start)
AS
(
---- Anchor member definition
SELECT l.NewLoanID, l.PreviousLoanID, 0 as start
FROM dscs_public.LoanRollup l
Where NewLoanID = 1108
UNION ALL
-- Recursive member definition
SELECT l.NewLoanID, l.PreviousLoanID, start + 1
FROM dscs_public.LoanRollup l
INNER JOIN OldLoans AS o
ON o.NewLoanID = l.PreviousLoanID
)
---- Statement that executes the CTE
SELECT PreviousLoanID, NewLoanID, start
FROM OldLoans
It fails with this error:
The statement terminated. The maximum recursion 100 has been exhausted
before statement completion.
Can anyone spot my mistake please?
Thanks.
The aliases in the CTE definition are in the wrong order:
-- Instead of (PreviousLoanID, NewLoanID, start)
WITH OldLoans (NewLoanID, PreviousLoanID, start)
AS
(
---- Anchor member definition
SELECT l.NewLoanID, l.PreviousLoanID, 0 as start
FROM mytable l --LoanRollup l
Where NewLoanID = 1108
UNION ALL
-- Recursive member definition
SELECT l.NewLoanID, l.PreviousLoanID, start + 1
FROM mytable l --dscs_public.LoanRollup l
INNER JOIN OldLoans AS o
-- Instead of o.NewLoanID = l.PreviousLoanID
ON l.NewLoanID = o.PreviousLoanID
)
---- Statement that executes the CTE
SELECT PreviousLoanID, NewLoanID, start
FROM OldLoans
The same thing holds for the ON clause in the recursive member definition.
I have a table with customer_number, week, and sales. I need to check if there were 12 consecutive weeks of no sales for each customer and create a flag of 0/1.
I can check the last 12 weeks or a certain time frame, but what's the best way to check for consecutive runs? Here is the code I have so far:
select * from weekly_sales
where customer_nbr in (123, 234)
and week < '2015-11-01'
and week > '2014-11-01'
order by customer_nbr, week
;
Sql Fiddle Demo
Here is a simplify version only need a week_id and sales
SELECT S1.weekid start_week, MAX(S2.weekid) end_week, SUM (S2.sales)
FROM Sales S1
JOIN Sales S2
ON S2.weekid BETWEEN S1.weekid and S1.weekid + 11
WHERE S1.weekid BETWEEN 1 and 25 -- your search range
GROUP BY S1.weekid
Let me know if that work for you
OUTPUT
| start_week | end_week | |
|------------|----------|----|
| 1 | 12 | 12 |
| 2 | 13 | 8 |
| 3 | 14 | 3 |
| 4 | 15 | 2 |
| 5 | 16 | 0 | <-
| 6 | 17 | 0 | <- no sales for 12 week
| 7 | 18 | 0 | <-
| 8 | 19 | 4 |
| 9 | 20 | 9 |
| 10 | 21 | 11 |
| 11 | 22 | 15 |
| 12 | 23 | 71 |
| 13 | 24 | 78 |
| 14 | 25 | 86 |
| 15 | 25 | 86 | < - less than 12 week range
| 16 | 25 | 86 | < - below this line
| 17 | 25 | 86 |
| 18 | 25 | 86 |
| 19 | 25 | 86 |
| 20 | 25 | 82 |
| 21 | 25 | 77 |
| 22 | 25 | 75 |
| 23 | 25 | 71 |
| 24 | 25 | 15 |
| 25 | 25 | 8 |
Your final query should have
HAVING SUM (S2.sales) = 0
AND COUNT(*) = 12
Ummmmm...You could use between 'week' and 'week', and you can use too the "count(column)" in order to improve performance.
So you only have to compare if result is bigger than 0
i need to delete all duplicate rows in my table - but leave only one row
MyTbl
====
Code | ID | Place | Qty | User
========================================
1 | 22 | 44 | 34 | 333
2 | 22 | 44 | 34 | 333
3 | 22 | 55 | 34 | 333
4 | 22 | 44 | 34 | 666
5 | 33 | 77 | 12 | 999
6 | 44 | 11 | 87 | 333
7 | 33 | 77 | 12 | 999
i need to see this:
Code | ID | Place | Qty | User
=======================================
1 | 22 | 44 | 34 | 333
3 | 22 | 55 | 34 | 333
4 | 22 | 44 | 34 | 666
5 | 33 | 77 | 12 | 999
6 | 44 | 11 | 87 | 333
In most databases, the fastest way to do this is:
select distinct t.*
into saved
from mytbl;
delete from mytbl;
insert into mytbl
select *
from saved;
The above syntax should work in Access. Other databases would use truncate table instead of delete.
Try this,
WITH CTEMyTbl (A,duplicateRecCount)
AS
(
SELECT id,ROW_NUMBER() OVER(PARTITION by id,place,qty,us ORDER BY id)
AS duplicateRecCount
FROM MyTbl
)
DELETE FROM CTEMyTbl
WHERE duplicateRecCount > 1
I'm using SQL Server 2008 R2. I have a table called tstResult in my database.
AI SubID StudID StudName TotalMarks ObtainedMarks
--------------------------------------------------------
1 | 1 | 1 | Jakir | 100 | 90
2 | 1 | 2 | Rubel | 100 | 75
3 | 1 | 3 | Ruhul | 100 | 82
4 | 1 | 4 | Beauty | 100 | 82
5 | 1 | 5 | Bulbul | 100 | 96
6 | 1 | 6 | Ripon | 100 | 82
7 | 1 | 7 | Aador | 100 | 76
8 | 1 | 8 | Jibon | 100 | 80
9 | 1 | 9 | Rahaat | 100 | 82
Now I want a SELECT query that generate a merit list according to the Obtained Marks. In this query obtained marks "96" will be the top in the merit list and all the "82" marks will be placed one after another in the merit list. Something like this:
StudID StudName TotalMarks ObtainedMarks Merit List
----------------------------------------------------------
| 5 | Bulbul | 100 | 96 | 1
| 1 | Jakir | 100 | 90 | 2
| 9 | Rahaat | 100 | 82 | 3
| 3 | Ruhul | 100 | 82 | 3
| 4 | Beauty | 100 | 82 | 3
| 6 | Ripon | 100 | 82 | 3
| 8 | Jibon | 100 | 80 | 4
| 7 | Aador | 100 | 76 | 5
| 2 | Rubel | 100 | 75 | 6
;with cte as
(
select *, dense_rank() over (order by ObtainedMarks desc) as Merit_List
from tstResult
)
select * from cte order by Merit_List desc
you need to use Dense_rank()
select columns from tstResult order by ObtainedMarks desc
I have a database with sample data represented by Table 1 below. How do I write an SQL query to display them in either Table 2 or Table 3 format?
Table 1 Table 2
Date | Value Year | Week | Total Value | % Change
------------+------- ------+-----+--|---------------|----------
19/12/2011 | 60 2012 | 1 | 295 | 656.41%
20/12/2011 | 49 2012 | 0 | 39 | -80.98%
21/12/2011 | 42 2012 | 52 | 205 | -41.76%
22/12/2011 | 57 2011 | 51 | 352 |
23/12/2011 | 88
24/12/2011 | 18 Table 3
25/12/2011 | 38 Year | Week | SUM1 | Year | Week | SUM2 | % Change
26/12/2011 | 16 ------+--------+--------+--------+--------+--------+-----------
27/12/2011 | 66 2012 | 1 | 295 | 2012 | 0 | 39 | 656.41%
28/12/2011 | 21 2012 | 0 | 39 | 2011 | 52 | 205 | -80.98%
29/12/2011 | 79 2011 | 52 | 205 | 2011 | 51 | 352 | -41.76%
30/12/2011 | 7 2011 | 51 | 352 |
31/12/2011 | 16
01/01/2012 | 39
02/01/2012 | 17
03/01/2012 | 86
04/01/2012 | 55
05/01/2012 | 82
06/01/2012 | 0
07/01/2012 | 9
08/01/2012 | 46
My preference would be to run 1 query to aggregate Table 1 to the year/week level and then do the "% change" in another language, depending on your environment. However, if you truly needed a SQL-only solution, you could do something like this.
create table t1 as
select year(Date) as year, week(Date) as week, sum(Value) as totalvalue
from table1
group by year(Date) as year, week(Date) as week
order by Date desc
;
select a.year, a.month, a.totalvalue,
(a.totalvalue-b.totalvalue)/b.totalvalue as pct_change
from (
select year, month, totalvalue,
case when week>1 then week-1 else 52 end as prevweek,
case when week>1 then year else year-1 end as prevyear
from t1
) a
left outer join t1 b
on a.prevweek=b.week and a.prevyear =b.year
;