SQL Rearrange row order - sql

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

Related

How to update table by of the records in the table

I have a table in PostgerSQL and I need to make N entries in the table twice and for the first half I need to fill in the partner_id field with the value 1 and the second half with the value partner_id = 2.
i try to `
update USERS_TABLE set user_rule_id = 1;
update USERS_TABLE set user_rule_id = 2 where USERS_TABLE.id > count(*)/2;
`
I depends a lot how precise the number of users have to be that are updated with 1 or 2.
The following would be quite unprecise,a s it doesn't take the exact number of user that already exist8after deleting some rows the numbers doesn't fit anymore.
SELECT * FROM USERS_TABLE
id
user_rule_id
1
1
2
1
3
2
4
2
5
2
SELECT 5
If you have a lot of deleted rows and want still the half of the users, you can choose following approach, which does rely on the id, but at teh actual row number
UPDATE USERS_TABLE1
set user_rule_id = CASE WHEN rn <= (SELECT count(*) FROM USERS_TABLE1)/ 2 then 1
ELSE 2 END
FROM (SELECT id, ROW_NUMBER() OVER( ORDER BY id) rn FROM USERS_TABLE1) t
WHERE USERS_TABLE1.id = t.id;
UPDATE 5
SELECT * FROM USERS_TABLE1
id
user_rule_id
1
1
2
1
3
2
4
2
5
2
SELECT 5
fiddle
In the sample case it it the same result, but when you have a lot of rows and a bunch of the deleted users, the senind will give you quite a good result

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;

how to set a range of defaults in a count query

I have a simple table of values:
column1
-------
2
5
7
5
8
7
and this simple query of number count:
SELECT column1, count(column1) as counter
FROM table
GROUP BY column1
ORDER BY count(column1) DESC
The question how can I add rows with values 0 when I have a number range for example from 1 to 8.
I want to get the result like this:
column1 Counter
-------- -------
5 2
7 2
2 1
8 1
1 0 <-- Row Add
2 0 <-- Row Add
3 0 <-- Row Add
4 0 <-- Row Add
6 0 <-- Row Add
Thanks very much.
If you are willing to use more than 1 query and to put your range of numbers in a table at least temporarily then you can do this with a full outer join. To do a Full outer join in access you combine a left join and a right join using either UNION OR UNION ALL.
copy the sql from the right and left joins into a union query then add the union and the order by statements to the union query.
SELECT SpecialNumbers.Numbers, mytable.Column1, Count(mytable.Column1) AS CountOfColumn1
FROM SpecialNumbers LEFT JOIN mytable ON SpecialNumbers.Numbers = mytable.Column1
GROUP BY SpecialNumbers.Numbers, mytable.Column1
UNION
SELECT SpecialNumbers.Numbers, mytable.Column1, Count(mytable.Column1) AS CountOfColumn1
FROM SpecialNumbers RIGHT JOIN mytable ON SpecialNumbers.Numbers = mytable.Column1
GROUP BY SpecialNumbers.Numbers, mytable.Column1
ORDER BY CountOfColumn1 DESC;
Given my special numbers where 1 to 10 This turns
to
Assuming that you only wish the four missing rows added, this is not that difficult in Access, as it is easy to create a small query generating numbers from a system table:
SELECT
T.Column1,
Count(Table.[Column1]) AS [Counter]
FROM
(SELECT DISTINCT Abs([id] Mod 10) AS Column1
FROM MSysObjects
WHERE (Abs([id] Mod 10)) Between 1 And 8) As T
LEFT JOIN
[Table]
ON T.Column1 = Table.Column1
GROUP BY
T.Column1
ORDER BY
Count(Table.[Column1]) DESC,
T.Column1;
Output:

insert sql records

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.

Returning several rows from a single query, based on a value of a column

Let's say I have this table:
|Fld | Number|
1 5
2 2
And I want to make a select that retrieves as many Fld as the Number field has:
|Fld |
1
1
1
1
1
2
2
How can I achieve this? I was thinking about making a temporary table and instert data based on the Number, but I was wondering if this could be done with a single Select statement.
PS: I'm new to SQL
You can join with a numbers table:
SELECT Fld
FROM yourtable
JOIN Numbers
ON yourtable.Number <= Numbers.Number
A numbers table is just a table with a list of numbers:
Number
1
2
3
etc...
Not an great solution (since you still query your table twice, but maybe you can work from it)
SELECT t1.fld, t1.number
FROM table t1, (
SELECT ROWNUM number FROM dual
CONNECT BY LEVEL <= (SELECT MAX(number) FROM t1)) t2
WHERE t2.number<=t1.number
It generates maximum amount of rows needed and then filters it by each row.
I don't know if your RDBMS version supports it (although I rather suspect it does), but here is a recursive version:
WITH remaining (fld, times) as (SELECT fld, 1
FROM <table>
UNION ALL
SELECT a.fld, a.times + 1
FROM remaining as a
JOIN <table> as b
ON b.fld = a.fld
AND b.number > a.times)
SELECT fld
FROM remaining
ORDER BY fld
Given your source data table, it outputs this (count included for verification):
fld times
=============
1 1
1 2
1 3
1 4
1 5
2 1
2 2