I have a table with an ARR column storing various values. I have to generate row number when my ARR column has value 4.
My table
Sno Data ARR
----------------
1 AAA 0
2 AAA 1
3 AAA 1
4 AAA 2
5 AAA 3
6 AAA 4
7 AAA 5
8 AAA 5
9 AAA 6
10 AAA 4
11 AAA 5
12 AAA 6
Required result:
Sno Data ARR RowNumber
----------------------------
1 AAA 0 0
2 AAA 1 0
3 AAA 1 0
4 AAA 2 0
5 AAA 3 0
6 AAA 4 1
7 AAA 5 2
8 AAA 5 3
9 AAA 6 4
10 AAA 4 1
11 AAA 5 2
12 AAA 6 3
Here at Sno=10 (value 4 in ARR), the rownumber starts again at 1.
I think you want:
select t.sno, t.data, t.arr,
(case when grp >= 1
then row_number() over (partition by grp order by sno)
else 0
end) as rownumber
from (select t.*,
sum(case when arr = 4 then 1 else 0 end) over (order by sno) as grp
from t
) t;
Related
I'd like to divide the data into separate groups (chunks) based on the value in the column. If the value increase above certain threshold, the value in the "group" should increase by 1.
This would be easy to achieve in MySQL, by doing CASE WHEN #val > 30 THEN #row_no + 1 ELSE #row_no END however I am using Amazon Redshift where this is not allowed.
Sample fiddle: http://sqlfiddle.com/#!15/00b3aa/6
Suggested output:
ID
Value
Group
1
11
1
2
11
1
3
22
1
4
11
1
5
35
2
6
11
2
7
11
2
8
11
2
9
66
3
10
11
3
A cumulative sum should do what you want:
SELECT *, sum((val>=30)::INTEGER) OVER (ORDER BY id BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM mydata ORDER BY id;
id | val | sum
----+-----+-----
1 | 11 | 0
2 | 11 | 0
3 | 22 | 0
4 | 11 | 0
5 | 35 | 1
6 | 11 | 1
7 | 11 | 1
8 | 11 | 1
9 | 66 | 2
10 | 11 | 2
I have a table [dbo].[UserImages] where user uploads their photos after every 6 day, total 18 records for user 3. 9 records of day 1 and 9 records of day 6. There are 4 columns In this table
[Id, UserId, Image, Day]
Id UserId Image Day
1 3 3_20200408_1.png 1
2 3 3_20200408_2.png 1
3 3 3_20200408_3.png 1
4 3 3_20200408_4.png 1
5 3 3_20200408_5.png 1
6 3 3_20200408_6.png 1
7 3 3_20200408_7.png 1
8 3 3_20200408_8.png 1
9 3 3_20200408_9.png 1
10 3 3_20200410_9.png 6
11 3 3_20200410_2.png 6
12 3 3_20200410_3.png 6
13 3 3_20200410_4.png 6
14 3 3_20200410_5.png 6
15 3 3_20200410_6.png 6
16 3 3_20200410_7.png 6
17 3 3_20200410_8.png 6
18 3 3_20200410_9.png 6
I need something like that
ImgCount UserId ImageDay1 ImageDay6
1 3 3_20200408_1.png 3_20200408_1.png
2 3 3_20200408_2.png 3_20200408_2.png
3 3 3_20200408_3.png 3_20200408_3.png
4 3 3_20200408_4.png 3_20200408_4.png
5 3 3_20200408_5.png 3_20200408_5.png
6 3 3_20200408_6.png 3_20200408_6.png
7 3 3_20200408_7.png 3_20200408_7.png
8 3 3_20200408_8.png 3_20200408_8.png
9 3 3_20200408_9.png 3_20200408_9.png
What should I do for this
You can use row_number() and aggregation:
select
imgCount,
userId,
max(case when day = 1 then image end) ImageDay1,
max(case when day = 6 then image end) ImageDay6
from (
select t.*, row_number() over(partition by userId, day order by image) imgCount
from mytable t
where day in (1, 6)
) t
group by userId, imgCount
order by ImgCount
Demo on DB Fiddle:
ImgCount | userId | ImageDay1 | ImageDay6
:------- | -----: | :--------------- | :---------------
1 | 3 | 3_20200408_1.png | 3_20200410_1.png
2 | 3 | 3_20200408_2.png | 3_20200410_2.png
3 | 3 | 3_20200408_3.png | 3_20200410_3.png
4 | 3 | 3_20200408_4.png | 3_20200410_4.png
5 | 3 | 3_20200408_5.png | 3_20200410_5.png
6 | 3 | 3_20200408_6.png | 3_20200410_6.png
7 | 3 | 3_20200408_7.png | 3_20200410_7.png
8 | 3 | 3_20200408_8.png | 3_20200410_8.png
9 | 3 | 3_20200408_9.png | 3_20200410_9.png
What I currently have:
ID FROM_REF TO_REF
--- -------- ----
1 1 10
1 2 3
1 3 4
1 3 5
1 5 6
1 6 7
1 7 9
1 8 11
1 9 8
1 10 2
What's needed is the SORT column which I can use to sort according later on:
ID FROM_REF TO_REF SORT
--- -------- ---- ----
1 1 10 1
1 10 2 2
1 2 3 3
1 3 4 4
1 4 5 5
1 5 6 6
1 6 7 7
1 7 9 8
1 9 8 9
1 8 11 10
NOTE: TO_REF column indicate next FROM_REF.
How do I write SQL to achieve the SORT column as result?
Please help.
You can use a RECURSIVE function.
WITH X (ID, FROM_REF, TO_REF) AS
(
SELECT ID, FROM_REF, TO_REF
FROM tbl
WHERE FROM_REF = 1
UNION ALL
SELECT tbl.ID, tbl.FROM_REF, tbl.TO_REF
FROM tbl
JOIN X
ON tbl.ID = X.ID
AND tbl.FROM_REF = X.TO_REF
)
SELECT ID, FROM_REF, TO_REF
FROM X
ID | FROM_REF | TO_REF
-: | -------: | -----:
1 | 1 | 10
1 | 10 | 2
1 | 2 | 3
1 | 3 | 4
1 | 4 | 5
1 | 5 | 6
1 | 6 | 7
1 | 7 | 9
1 | 9 | 8
1 | 8 | 11
dbfiddle here
A simple hierarchical query, I presume.
SQL> with test (from_ref, to_ref) as
2 (select 1, 10 from dual union
3 select 2, 3 from dual union
4 select 3, 4 from dual union
5 select 4, 5 from dual union
6 select 5, 6 from dual union
7 select 6, 7 from dual union
8 select 7, 9 from dual union
9 select 8, 11 from dual union
10 select 9, 8 from dual union
11 select 10, 2 from dual
12 )
13 select from_ref, to_ref, level rn
14 from test
15 connect by from_ref = prior to_ref
16 start with from_ref = (select min(from_ref) from test);
FROM_REF TO_REF RN
---------- ---------- ----------
1 10 1
10 2 2
2 3 3
3 4 4
4 5 5
5 6 6
6 7 7
7 9 8
9 8 9
8 11 10
10 rows selected.
SQL>
Would like to count records in the result of aggregate query. So if my original data looks like this:
========================
Field 1 Field 2 Field 3
------------------------
aaa ccc 10
aaa ccc 10
aaa ddd 10
aaa ddd 10
bbb ddd 10
bbb ddd 10
bbb eee 10
I group by Field 1, Field 2 and I do Sum of Field 3
So result looks:
========================
Field 1 Field 2 Field 3
------------------------
aaa ccc 20
aaa ddd 20
bbb ddd 20
ddd eee 10
I would like to count, how many times each value appears in Field 1 and Field 2.
So that result would look like this:
======================================================
Field 1 Field 2 Field 3 Count Field 1 Count Field 2
------------------------------------------------------
aaa ccc 20 2 1
aaa ddd 20 2 2
bbb ddd 20 2 2
ddd eee 10 2 1
I tried to use Cound function, but it counts original table, so shows result of original table, I get result:
======================================================
Field 1 Field 2 Field 3 Count Field 1 Count Field 2
------------------------------------------------------
aaa ccc 20 4 2
aaa ddd 20 4 4
bbb ddd 20 3 4
ddd eee 10 3 1
Most databases support window/analytic functions. These can be combined in aggregations to do what you want:
select field1, field2, sum(field3) as sumfield3,
count(*) over (partition by field1) as numField1,
count(*) over (partition by field2) as numField2
from table t
group by tield1, field2;
I'm looking to create a histogram in SQL (which in itself isn't too tricky), but what I'm looking for is a way of splitting the bins so that each bin / band has the same proportion of the data included within.
For example if I have the sample data (the value column) and I want to divide it into 5 bins, I know that I can work out the number of bins by doing something like
(MAX(Value) - MIN(Value)) / numberofsteps
Will give the groups we see in the band 1 column.
However what I want is for the bands to be calculated so that each band accounts for (100 / n) % of the total where n is the number of bands (so in this case each of the 5 bands would represent 20% of the total data) - which is what is shown in the band 2 column
Value band 1 band 2
1 | 1 to 2 | 0 to 1
1 | 1 to 2 | 0 to 1
1 | 1 to 2 | 0 to 1
1 | 1 to 2 | 0 to 1
2 | 1 to 2 | 2 to 3
2 | 1 to 2 | 2 to 3
3 | 1 to 2 | 2 to 3
3 | 1 to 2 | 2 to 3
4 | 3 to 4 | 4 to 6
4 | 3 to 4 | 4 to 6
5 | 5 to 6 | 4 to 6
6 | 5 to 6 | 4 to 6
7 | 7 to 8 | 7 to 8
8 | 7 to 8 | 7 to 8
8 | 7 to 8 | 7 to 8
8 | 7 to 8 | 7 to 8
9 | 9 to 10 | 9 to 10
10 | 9 to 10 | 9 to 10
10 | 9 to 10 | 9 to 10
10 | 9 to 10 | 9 to 10
Is there a way to do this in SQL (i'm using SQL server 2005 if that helps), possibly without creating a UDF and having it so that I can easily alter the number of bins would be great (if that's not asking the impossible!)
Thanks
To divide into bins you can use the ntile function.
with Vals AS
(
SELECT 1 AS value UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 8 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 10 UNION ALL SELECT 10
), TiledVals AS
(
SELECT value, NTILE(5) OVER (ORDER BY value) AS BinNumber
FROM Vals
)
SELECT value, BinNumber,
Min(value) OVER (PARTITION BY BinNumber) As StartBin,
MAX(value) OVER (PARTITION BY BinNumber) As EndBin
FROM TiledVals
Gives
value BinNumber StartBin EndBin
----------- -------------------- ----------- -----------
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
2 2 2 3
2 2 2 3
3 2 2 3
3 2 2 3
4 3 4 6
4 3 4 6
5 3 4 6
6 3 4 6
7 4 7 8
8 4 7 8
8 4 7 8
8 4 7 8
9 5 9 10
10 5 9 10
10 5 9 10
10 5 9 10