insert sql records - sql

I have a data like
1
2
1
1
2
2
1
1
1
1
2
2
2
2
I need to order the data like
1
2
1
2
1
2
1
2
the 3rd row "1" and the 5th row "2" should be ordered. Likewise 7th row "1" and the 10th row "2", 8th row "1" and the 11th row "2" etc.
In general, if the continuous count of "1" is 5, there will be 5 records with the value "2". 1->6,2->7,3->8 likewise it should be ordered.
Can you please tell me the logic in sql query? thanks in advance.

You can use row_number():
select t.*
from t
order by row_number() over (partition by col order by col);
If you have an ordering that you want between groups, then use that for the order by in the windowing clause.

If your dbms supports window functions you can order 1s and 2s this way
select col
from tbl
order by 2*row_number() over(partition by col order by col) + case col when 1 then 0 else 1 end;
but there is no way to tell where was any row in the query result in the source, insert into tbl(col) values (1),(1),... statement for example.

Related

Snowflake: Repeating rows based on column value

How to repeat rows based on column value in snowflake using sql.
I tried a few methods but not working such as dual and connect by.
I have two columns: Id and Quantity.
For each ID, there are different values of Quantity.
So if you have a count, you can use a generator:
with ten_rows as (
select row_number() over (order by null) as rn
from table(generator(ROWCOUNT=>10))
), data(id, count) as (
select * from values
(1,2),
(2,4)
)
SELECT
d.*
,r.rn
from data as d
join ten_rows as r
on d.count >= r.rn
order by 1,3;
ID
COUNT
RN
1
2
1
1
2
2
2
4
1
2
4
2
2
4
3
2
4
4
Ok let's start by generating some data. We will create 10 rows, with a QTY. The QTY will be randomly chosen as 1 or 2.
Next we want to duplicate the rows with a QTY of 2 and leave the QTY =1 as they are.
Obviously you can change all parameters above to suit your needs - this solution works super fast and in my opinion way better than table generation.
Simply stack SPLIT_TO_TABLE(), REPEAT() with a LATERAL() join and voila.
WITH TEN_ROWS AS (SELECT ROW_NUMBER()OVER(ORDER BY NULL)SOME_ID,UNIFORM(1,2,RANDOM())QTY FROM TABLE(GENERATOR(ROWCOUNT=>10)))
SELECT
TEN_ROWS.*
FROM
TEN_ROWS,LATERAL SPLIT_TO_TABLE(REPEAT('hire me $10/hour',QTY-1),'hire me $10/hour')ALTERNATIVE_APPROACH;

SQL Query getting the latest record of the Group and calculate the value of those particular records

I do have the following table (just a sample) and would like to get the Points subtract from Record2 to Record1. (Record2-Record1) from the latest record of both record1 and 2. The records are entered in category of Match. 1 Match will consists of 2 records which are Record 1 and Record 2.
The output will be 3 as the newest record is ID 3 and 4 from the Match2.)
ID
Name
Points
TimeRecorded
Match
1
Record 1
3
2-Mar 2pm
1
2
Record 2
5
2-Mar 2pm
1
3
Record 1
5
4-Mar 5pm
2
4
Record 2
8
4-Mar 5pm
2
I tried to get the value of subtracting both query as below. But I feel that this is not the good way as it is hard coded for the match and the Name of the record. May I know how to construct a better query in order to get the latest record of the grouped match and calculate the points whereby subtracting Record1 from Record2.
SELECT
(select Points from RunRecord where Name= 'Record2' AND Match = 2)
- (select Points from RunRecord where Name= 'Record1' AND Match = 2)
You could use:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY Name ORDER BY TimeRecorded DESC) rn
FROM yourTable
)
SELECT
MAX(CASE WHEN Name = 'Record 2' THEN Points END) -
MAX(CASE WHEN Name = 'Record 1' THEN Points END) AS diff
FROM cte
WHERE rn = 1;
The CTE assigns a row number for each group of records of the same name, with 1 being assigned to the most recent record. Then, we aggregate over the entire table and pivot out the points to find the difference.
You can use the rank() window function to rank the records by match descending. Then take the top of the ranked records and use conditional aggregation to control the sign of the points added.
SELECT sum(CASE x.name
WHEN 'Record2' THEN
x.points
WHEN 'Record1' THEN
-x.points
END)
FROM (SELECT rr.name,
rr.points,
rank() OVER (ORDER BY rr.match DESC) r
FROM runrecord rr
WHERE name IN ('Record1',
'Record2')) x
WHERE x.r = 1;

columns to rows change in oracle sql

I have columns a,b in table x.And i want to change this columns data into rows.
it is possible to have duplicate vales in table but in columns to row change only distinct values should come.
E.G:
a b
1 2
1 11
3 4
5 6
7 8
9 10
......etc
the result 1 (query 1) should be 1-2,1-11,3-4,5-6,7-8,9-10.....etc
The result 2 (query 2) should b 1,3,5,7,9....etc(only one 1 must come as we have duplicate data for column a)
how can i achieve this in oracle SQL.
Please help.
For Oracle 11 use function listagg() and in first query concatenate columns, in second - select distinct values at first.
Query 1:
select listagg(a||'-'||b, ',') within group (order by a, b) result from t
RESULT
------------------------------
1-2,1-11,3-4,5-6,7-8,9-10
Query 2:
select listagg(a, ',') within group (order by a) result
from (select distinct a from t)
RESULT
------------------------------
1,3,5,7,9
For older versions you can use wmsys.wm_concat.

Selecting N+1th highest row in Oracle if it exists or else return Nth highest

In a table with M Columns, I want the row that contains the (n+1)th highest value in Column J given the nth highest value of Column J. If there is no (n+1)th highest value of Column J, then the query should return the row containing the nth highest value in Column J.
Is it possible that I can do this using a single query using rownum or rank() ?
For Example In the below table if I want to run the query on Column B,
A B C
=============
1 3 4 -> ROW1
8 4 5 -> ROW2
9 5 2 -> ROW3
0 0 1 -> ROW4
QUERY(ROW1) => returns ROW4 since ROW4 has the next highest value for
Col B which is 0 QUERY(ROW2) => returns ROW1 since ROW1 has the next
highest value for Col B which is 3
But if I run QUERY(ROW4), it should return ROW4 itself since there is
no other lower value for Col B.
By next highest I mean the N+1th highest value when sorted in Descending order. SO there is no next highest value for the lowest value.
Is it possible that I can do this using a single query?
Something like this?
WITH subquery AS (
SELECT *,
ROW_NUMBER() OVER (ORDER BY ColumnJ DESC) AS row_id
FROM table_name
)
SELECT *
FROM subquery
WHERE row_id = CASE WHEN :required_rank = (SELECT MAX(row_id) FROM subquery)
THEN :required_rank
ELSE :required_rank + 1 END;
Do you mean something like:
SELECT * FROM some_table
WHERE B IN (SELECT nvl(max(B), ?) FROM some_table WHERE B < ?)
SQLFiddle example.

SQL Rearrange row order

Problem:
A row in my_table contains
1
2
3
3
4
4
4
I want to rearrange the row order to the following
4
4
4
1
3
3
2
Is there any way I can perform this?
I have not written any code so far. ( I do not know how to begin)
Just use CASE in the ORDER BY - it's much cleaner and easier to read.
...
ORDER BY CASE WHEN YourColumn = 4 then 0
WHEN YourColumn = 2 then 1
ELSE 2 END, yourcolumn
It's also a bad idea to change the order of the rows since there is actually no inherent order in SQL - it's all in the presentation layer, so use ORDER BY in your SELECTs to accomplish it.
as Adam Wenger said,
or if you wanted, it could be done in your table, meaning your sql statement can remain as a basic select * from table order by newcolumn*
*see below
add a new column
update each row set column=1 where original_column=4
update each row set column=2 where original_column=2
update each row set column=3 where original_column=1
update each row set column=4 where original_column=3
and then order by this new column.
Create a lookup table with the original value and the corresponding sort order:
SortLookupTable:
OriginalValue, SortOrder
1, 2
2, 4
3, 3
4, 1
Then join the table to your original table
SELECT T.*
FROM
MyTable T
INNER JOIN SortLookupTable S
ON T.Value = S.OriginalValue
ORDER BY
S.SortOrder;
SELECT yourColumn
FROM
(
SELECT yourColumn
, CASE yourColumn
WHEN 4 THEN 1
WHEN 1 THEN 2
WHEN 3 THEN 3
WHEN 2 THEN 4
END AS SortColumn
FROM yourTable
) AS t
ORDER BY t.SortColumn ASC
This will sort 4, 1, 3, 2