I have a data like
id1,apple,0
id2,orange,0
id3,banana,0
id4,carrot,0
ida,kiwi,1
idb,potato,1
idc,cakes,1
idd,chocos,1
I need to shuffle on the base of last column (0 THEN 1) like
id1,apple,0
ida,kiwi,1
id2,orange,0
idb,potato,1
id3,banana,0
idc,cakes,1
id4,carrot,0
idd,chocos,1
Is that possible in sqlite or in notepad++ ??
If the version of SQLite you use supports it you can do it with row_number() window function:
select t.id, t.fruit, t.number
from (
select *,
row_number() over (partition by number order by id) rn
from tablename
) t
order by t.rn
If you need the rows shuffled, replace order by id with order by random().
See the demo.
If you can't use window functions:
select t.id, t.fruit, t.number
from (
select t.*,
(select count(*) from tablename where number = t.number and id < t.id) rn
from tablename t
) t
order by t.rn
See the demo.
Results:
| id | fruit | number |
| --- | ------ | ------ |
| id1 | apple | 0 |
| ida | kiwi | 1 |
| id2 | orange | 0 |
| idb | potato | 1 |
| id3 | banana | 0 |
| idc | cakes | 1 |
| id4 | carrot | 0 |
| idd | chocos | 1 |
You can do this using row_number() in the order by clause:
select t.*
from t
order by row_number() over (partition by col3 order by col1),
col1;
Often "shuffle" implies randomness ("interleaving" would not). If that is what you mean:
select t.*
from t
order by row_number() over (partition by col3 order by random()),
col1
Related
I working on a query for SQL Server 2016. I have order by serial_no and group by pay_type and I would like to add row number same example below
row_no | pay_type | serial_no
1 | A | 4000118445
2 | A | 4000118458
3 | A | 4000118461
4 | A | 4000118473
5 | A | 4000118486
1 | B | 4000118499
2 | B | 4000118506
3 | B | 4000118519
4 | B | 4000118521
1 | A | 4000118534
2 | A | 4000118547
3 | A | 4000118550
1 | B | 4000118562
2 | B | 4000118565
3 | B | 4000118570
4 | B | 4000118572
Help me please..
SELECT
ROW_NUMBER() OVER(PARTITION BY paytype ORDER BY serial_no) as row_no,
paytype, serial_no
FROM table
ORDER BY serial_no
You can assign groups to adjacent pay types that are the same and then use row_number(). For this purpose, the difference of row numbers is a good way to determine the groups:
select row_number() over (partition by pay_type, seqnum - seqnum_2 order by serial_no) as row_no,
t.*
from (select t.*,
row_number() over (order by serial_no) as seqnum,
row_number() over (partition by pay_type order by serial_no) as seqnum_2
from t
) t;
This type of problem is one example of a gaps-and-islands problem. Why does the difference of row numbers work? I find that the simplest way to understand is to look at the results of the subquery.
Here is a db<>fiddle.
add this to your select list
ROW_NUMBER() OVER ( ORDER BY (SELECT 1) )
since you already sorting by your stuff, so you don't need to sorting in your windowing function so consuming less CPU,
Given the following example table:
+-----------+
| Id | Name |
+----+------+
| 1 | A |
| 2 | B |
| 3 | B |
| 4 | C |
| 5 | A |
| 6 | B |
| 7 | B |
| 8 | B |
| 9 | B |
| 10 | X |
+----+------+
I would like a query to get the following result:
+----+------+
| 6 | B |
| 7 | B |
| 8 | B |
| 9 | B |
+----+------+
The best query I could do was:
SELECT * FROM
(SELECT id, name, LEAD(id) OVER (ORDER BY id) t
FROM test WHERE name = 'B' ORDER BY id)
WHERE ID <> t-1;
sqlfiddle here
If you want the length and where it starts:
select min(id), max(id)
from (select t.*,
row_number() over (order by id) as seqnum,
row_number() over (partition by name order by id) as seqnum_1
from test t
) t
where name = 'B'
group by (seqnum - seqnum_1)
order by min(id) desc
fetch first 1 row only;
You can join back to the table to get the original rows.
Another method using window functions to count the number of non-Bs after a given row . . . and then choose the first:
select t.*
from (select t.*,
dense_rank() over (order by nonbs_after asc) as grp
from (select t.*,
sum(case when name <> 'B' then 1 else 0 end) over (order by id desc) as nonbs_after
from test t
) t
where name = 'B'
) t
where grp = 1;
Here is a db<>fiddle.
I have a table like
i want to select first and last record of every group by facility_id and created_at horizontally
need to output like . i can do it vertically but need horizontally
with CTE as (
select
*
,ROW_NUMBER() over (partition by facility_id,name order by created_at asc ) ascrnk
,ROW_NUMBER() over (partition by facility_id,name order by created_at desc ) desrnk
from TestTable
)
select T1.facility_id,T1.name,
T1.value as "First_value",
T1.created_at as "First created_at",
T2.value as "Last_value",
T2.created_at as "Last created_at"
from (
select * from cte
where ascrnk = 1
) T1
left join (
select * from cte
where desrnk = 1
) T2 on T1.facility_id = T2.facility_id and T1.name = T2.name
Result:
| facility_id | name | First_value | First created_at | Last_value | Last created_at |
|-------------|------|-------------|----------------------|------------|----------------------|
| 2011 | A | 200 | 2015-05-30T11:50:17Z | 300 | 2017-05-30T11:50:17Z |
| 2012 | B | 124 | 2015-05-30T11:50:17Z | 195 | 2017-05-30T11:50:17Z |
| 2013 | C | 231 | 2015-05-30T11:50:17Z | 275 | 2017-06-30T11:50:17Z |
| 2014 | D | 279 | 2017-06-30T11:50:17Z | 263 | 2018-06-30T11:50:17Z |
SQL Fiddle Demo Link
I think this is much simpler using window functions and select distinct:
select distinct facility_id, name,
first_value(value) over (partition by facility_id, name order by created_at asc) as first_value,
min(created_at) as first_created_at,
first_value(value) over (partition by facility_id, name order by created_at desc) as last_value,
max(created_at) as last_created_at
from t;
No subqueries. No joins.
You can also use arrays to accomplish the same functionality, using group by. It is a shame that SQL Server doesn't directly support first_value() as a window function.
I would like to do the rank the values over a partition with two columns. col1 will be the key and col2 will be some value that is also going to be used in ORDER BY. I would like to start a new partition only when col2 is discontinued. For example, I would like to do the following:
+------+------+------+
| col1 | col2 | rank |
+------+------+------+
| a | 1 | 1 |
| a | 2 | 2 |
| a | 3 | 3 |
| a | 9 | 1 |
| a | 10 | 2 |
| b | 1 | 1 |
| b | 2 | 2 |
| b | 8 | 1 |
+------+------+------+
Thinking somewhere in lines of
SELECT col1, RANK() OVER (PARTITION BY col1, SOMETHING HERE??? ORDER BY col2 DESC)
Does anyone have any ideas?
If I understand correctly, you want to enumerate by "islands" of adjoining sequential values. You can do so with a simple observation: subtracting a sequence from col2 will be constant for each group. So, let's use this observation:
select t.*,
row_number() over (partition by col1, grp order by col1) as rnk
from (select t.*,
(col2 - row_number() over (partition by col1 order by col2)) as grp
from t
) t
I have below table -
ID | Type | Val0 | Val1 | Group | Creation_date
1 | A | V1 | Val1 | G1 | 24sep, 2011
2 | A | V1 | Val2 | G1 | 27oct, 2008
3 | A | V2 | Val3 | G2 | 19oct, 2003
4 | B | X1 | Xal1 | G3 | 15 dec, 2001
5 | B | X2 | Xal2 | G4 | 15 dec, 2000
6 | B | X2 | Xal3 | G4 | 15 dec, 1990
7 | C | X3 | Xal4 | G5 | 23Dec, 2001
I want to keep only the latest values for a particular type and extract out values which are old but not belong to group with which the latest item is associated. So, for above table, I want these items to be extracted out - Val3, Xal2, Xal3 which i can delete later.
since A is having the latest value as Val1 which belongs to group G1, B is having the latest value as Xal1 and C is having the latest value as Xal4.
Can anybody suggest me how i can do this using SQL?
You can use row_number(). No aggregation is necessary:
select t.*
from (select t.*,
row_number() over (partition by t.type order by creation_date desc) as seqnum
from t
) t
where seqnum = 1;
However, you want the values that are not in this group. That is, you want the values from val1 where seqnum is not 1. This would be:
select t.val1
from (select t.*, min(seqnum) over (partition by t.type, t.group) as min_seqnum -- DON'T USE group FOR COLUMN NAMES!
from (select t.*,
row_number() over (partition by t.type order by creation_date desc) as seqnum
from t
) t
) t
where min_seqnum <> 1;
You can use ROW_NUMBER() :
SELECT p.type,p.val1 FROM (
SELECT t.*,
ROW_NUMBER() OVER(PARTITION BY t.type ORDER BY t.max_d DESC) as rnk
FROM (SELECT s.Type,s.Val1,MAX(s.creation_date) as max_d
FROM YourTable s
GROUP BY s.type,s.val1) t) p
WHERE p.rnk > 1