How to limit max rows in select query by key - sql

I have
ID ID2 Amount
-------- -------- ------
01 02 20
01 03 30
02 04 40
02 06 30
03 05 70
03 06 60
03 07 60
04 08 100
04 09 110
I want to query the data above into 2 resultset (return max 5 rows) which are:
result 1:
ID1 ID2 Amount
-------- -------- ------
01 02 20
01 03 30
02 04 40
02 06 30
result 2:
ID1 ID2 Amount
-------- -------- ------
03 05 70
03 06 60
03 07 60
04 08 100
04 09 110
How should I construct my query?

use row_number() to generate a sequential no. (row_number() over (order by ID1) - 1) / 5 + 1 will gives you set of 5 per each result
; WITH CTE AS
(
SELECT result_no = (row_number() over (order by ID1) - 1) / 5 + 1,
ID1, ID2, Amount
FROM yourtable
)
SELECT *
FROM CTE
WHERE result_no = #result_no

Related

Making a duplicate row in SQL table based on condition, and replacing a value in the new row

I have a table that looks something like this:
Agency Year Total PopGroup
01 2017 3467 3C
01 2018 3444 3C
01 2019 3567 3C
02 2017 1000 1C
02 2018 1354 1C
02 2019 1333 1C
03 2017 6784 2C
03 2018 3453 2C
04 2017 3333 2C
If an agency has a row for year 2019, I want to duplicate this row and call it 2020 (basically, an estimate population for 2020). Desired result:
Agency Year Total PopGroup
01 2017 3467 3C
01 2018 3444 3C
01 2019 3567 3C
01 2020 3567 3C
02 2017 1000 1C
02 2018 1354 1C
02 2019 1333 1C
02 2020 1333 1C
03 2017 6784 2C
03 2018 3453 2C
04 2017 3333 2C
I think I should use something like:
INSERT INTO table
WHERE Year = 2019
but I'm a little stuck. What can I try next?
You are on the right track:
INSERT INTO table (Agency, Year, Total, PopGroup)
SELECT Agency, 2020 as Year, Total, PopGroup
FROM table t
WHERE Year = 2019 ;
you can use the following insert to add a new row exactly same as another one but with some modified data.
insert into table (select agency, 2020, total, popgroup from table where year = 2019)
this will insert a new record exactly same as 2019 but with year 2020

How to get the first and the last value in a column per each sequence with the same value

I would like to get the first and the last value in the column Status1 of each sequence of the same value!
This is an example of my table:
time Status1 Eficiencia Lote
----------------------------------------------------
2020 06 14 18:03:48.457 70 80 95
2020 06 14 18:04:47.693 70 80 95
2020 06 14 18:06:58.203 55 80 95
2020 06 14 18:08:19.900 55 80 95
2020 06 14 18:09:45.537 55 80 95
2020 06 14 18:10:06.670 100 80 13
2020 06 14 18:10:27.297 100 80 13
2020 06 14 18:10:31.810 100 80 13
2020 06 14 18:10:43.187 100 80 13
2020 06 14 18:11:30.303 55 80 14
2020 06 14 18:12:07.563 55 80 14
2020 06 14 18:18:54.997 55 80 14
I tried this but using this I didn't get by each sequence but in the hole table!
;with cte as
(
select
*,
RnAsc = row_number() over (partition by [Status1] order by time),
RnDesc = row_number() over (partition by [Status1] order by time desc)
from
[VALORES_DB].[dbo].[OEE_TESTE]
)
select time, [Status1], Eficiencia, Lote, Status1
from cte
where RnAsc = 1 or RnDesc = 1
I would like to get the follow:
time Status1 Eficiencia Lote
------------------------------------------------------
2020 06 14 18:03:48.457 70 80 95
2020 06 14 18:04:47.693 70 80 95
2020 06 14 18:06:58.203 55 80 95
2020 06 14 18:09:45.537 55 80 95
2020 06 14 18:10:06.670 100 80 13
2020 06 14 18:10:43.187 100 80 13
2020 06 14 18:11:30.303 55 80 14
2020 06 14 18:18:54.997 55 80 14
I would suggest lag() and lead():
select t.*
from (select t.*,
lag(status1) over (order by time) as prev_status1,
lead(status1) over (order by time) as next_status1
from t
) t
where (prev_status1 is null or prev_status1 <> status1) or
(next_status1 is null or next_status1 <> status1);
These comparisons determine where the value changes -- which is really what you are asking for.

How to generate repeating numbers in sequence

I would like to generate this sequence
col sequence
01 01
01 02
01 03
01 04
01 05
02 01
02 02
02 03
02 04
02 05
..
..
12 01
12 02
12 03
12 04
12 04
And add this as a sequence to another select.
Hierarchical query might help to produce result you posted:
SQL> with
2 c1 as
3 (select lpad(1 + level - 1, 2, '0') col1
4 from dual
5 connect by level <= 12
6 ),
7 c2 as
8 (select lpad(1 + level - 1, 2, '0') col2
9 from dual
10 connect by level <= 5
11 )
12 select c1.col1, c2.col2
13 from c1 cross join c2
14 order by c1.col1, c2.col2;
CO CO
-- --
01 01
01 02
01 03
01 04
01 05
02 01
02 02
02 03
02 04
02 05
03 01
03 02
<snip>
11 04
11 05
12 01
12 02
12 03
12 04
12 05
60 rows selected.
SQL>
You want row_numner() :
select col, row_number() over (partition by col order by col) as sequence
from table t;
You can use sub-query for further operation.

Order by without top in SQL

I have a table Test with AcctNbr, Balance and Date columns. This table contains data as below
Acctnbr Balance LastUpdatedDt
123 100 May 08
456 200 May 08
222 300 May 07
333 400 May 07
123 50 May 06
222 120 May 05
678 70 May 04
Am trying to achieve daily balance as below
AcctNbr Balance LastUpdatedDt
123 100 May 08
456 200 May 08
222 300 May 08
333 400 May 08
123 50 May 08
678 70 May 08
123 50 May 07
456 0 May 07
222 300 May 07
333 400 May 07
123 50 May 07
678 70 May 07
123 50 May 06
456 0 May 06
222 120 May 06
333 0 May 06
123 50 May 06
678 70 May 06
123 0 May 05
456 0 May 05
222 120 May 05
333 0 May 05
123 0 May 05
678 70 May 05
123 0 May 04
456 0 May 04
222 0 May 04
333 0 May 04
123 0 May 04
678 70 May 04
Here is my query
SELECT
A.Accountnbr,
dt AS CalendarDate,
A.Balance
FROM
dbo.GetDates('20150504',GETDATE())
cross APPLY
(
SELECT TOP 1 Accountnbr,Balance
FROM dbo.Test
WHERE LastUpdateDt <= dt
ORDER BY LastUpdateDt DESC
) A
This is working fine when i use TOP and Order BY inside CROSS APPLY. But i want to get balances for all accounts. I cannot use TOP inside CROSS APPLY as Test table will be getting updated every day with new accounts, but i need Order By to get correct balances from To and End dates in GetDates function. My question is how to use Order by without using TOP in the above query. Any help is appreciated.
I would use a cte with a row number and partition on account number and date (assuming you want the latest by account and day).
You can then join any tables onto the cte table if you need to.
with balance_cte as (
SELECT Accountnbr,
LastUpdatedDt,
Balance,
row_number() over (partition by Accountnbr. mydate order by LastUpdateDt DESC) as rn
FROM dbo.Test
)
select Accountnbr,
LastUpdatedDt,
Balance
from join balance_cte
where rn = 1

Aggregate Query returning multiple records

I have the following table (simplified):
RecordID bigint IDENTITY
ItemID bigint
ConfigID varchar
Status varchar
StatusDate date
Sample Data:
001 04 1E 10 2007-08-14 13:57:54
002 04 1E 12 2007-08-21 16:10:21
003 04 1D 10 2007-09-27 17:14:13
004 04 1D 43 2011-01-10 13:44:50
005 04 1B 50 2008-06-20 09:09:51
006 05 1A 17 2007-12-18 14:04:56
007 05 1A 11 2007-10-17 08:23:52
008 05 1A 12 2007-10-19 12:54:18
009 05 1B 12 2007-11-02 09:23:54
010 05 1B 40 2010-06-17 09:34:33
011 07 1A 12 2007-11-19 14:48:06
012 07 1A 12 2007-11-19 15:02:48
013 07 1B 40 2011-01-10 14:36:16
014 08 1B 10 2009-05-22 11:14:42
015 08 1B 12 2007-11-20 17:02:44
016 08 1A 12 2007-12-12 16:11:57
017 08 1A 10 2009-11-12 11:12:45
018 08 1C 35 2011-01-10 18:30:10
019 08 1D 12 2009-10-14 14:34:47
020 08 1D 10 2009-10-14 14:35:09
Herein lies my problem:
I need to be able to have end-users query this data to return records that will display the latest status and statusdate for each unique combination of itemid and config. So, using the above sample I want to return a record set matching the following:
002 04 1E 12 2007-08-21 16:10:21
004 04 1D 43 2011-01-10 13:44:50
005 04 1B 50 2008-06-20 09:09:51
006 05 1A 17 2007-12-18 14:04:56
010 05 1B 40 2010-06-17 09:34:33
012 07 1A 12 2007-11-19 15:02:48
013 07 1B 40 2011-01-10 14:36:16
017 08 1A 10 2009-11-12 11:12:45
018 08 1C 35 2011-01-10 18:30:10
020 08 1D 10 2009-10-14 14:35:09
In plain english: I need to be able to return the latest status and status date for each item's configuration(s).
Any help in this regard would be extremely appreciated. Thank you in advance.
You can do the GROUP BY clause in a subquery. Try,
SELECT a.*
FROM yourtable a
INNER JOIN
(
SELECT ItemID, ConfigID, MAX([StatusDate]) maxStat
FROM yourtable
GROUP BY ItemID,ConfigID
) b on a.configID = b.configID AND
a.[statusDate] = b.MaxStat AND
a.ItemID = b.ItemID
Order by RecordID
SQLFiddle Demo
in SQL server 2005+, you can use CTE for this:
;with cte as
(
select recordid,
itemid,
configid,
status,
statusdate,
row_number() over(partition by itemid, configid
order by statusdate desc) rn
from yourtable
)
select *
from cte
where rn = 1
order by recordid
see SQL Fiddle with Demo
SELECT
RecordID,
ItemID,
ConfigID,
Status,
StatusDate
FROM
(SELECT
RecordID,
ItemID,
ConfigID,
Status,
StatusDate,
ROW_NUMBER() OVER(PARTITION BY ItemId,ConfigID ORDER BY StatusDate DESC) As StatusOrder
FROM
MyTable) Statuses
WHERE
StatusOrder= 1