Manipulate the sort result considering the user preference - database - sql

Suppose we have a simple database containing following data:
name
apple
pear
banana
grape
User want to sort those fruits by the name, and we will have, with no surprise
apple
banana
grape
pear
However, for some reason, user would like to place pear as the 3rd fruit ,that means he would like to have :
apple
banana
pear
grape
And, importantly, the user want to preserve this order when he want to sort the fruits by name thereafter.
How should we tackle this problem? Of top of my head, we could add a field user_sort_id, which will be updated when user sort and manipulate the sort result and we will use that filed as the sort key.
init value -> sort by name ->place pear as the seconds
name user_sort_id
apple 0 0 0
pear 1 3 2
banana 2 1 1
grape 3 2 3
This approach should work in theory. However, in practice, I can not think of an elegant and fast SQL statement that could accomplish this. Any ideas or alternatives?

If you want each user to have independent sort orders, you need another table.
CREATE TABLE user_sort_order (
name VARCHAR(?) NOT NULL REFERENCES your-other-table (name),
user_id INTEGER NOT NULL REFERENCES users (user_id),
sort_order INTEGER NOT NULL -- Could be float or decimal
);
Then ordering is easy.
SELECT name
FROM user_sort_order
WHERE user_id = ?
ORDER BY sort_order
There's no magic bullet for updating.
Delete all the user's rows, and insert rows with the new order. (Brute force always works.)
Update every row with the new order. (Could be a lot of UPDATE statements.)
Track the changes in your app, and update only the changed rows and the rows that have to be "bumped" by the changes. (Parsimonious, but error-prone.)
Don't let users impose their own sort order. (Usually not as bad an idea as it sounds.)

Related

How can I extract comma delimited values from one column and put them each in separate column in Google Data Studio?

Update: 1,2,3 are just examples it can also be 4,24,53
I have the following setup:
I store Data in BigQuery and use BigQuery as data source for my Data Studio project.
I have a column called Alarms and the data inside that column is as follow: it can be empty or 1 or 1,2 or 1,2,3 or 5,43,60 and so on. If it's empty or has 1 value then there is nothing to worry about, but if there are 2 or more values I have to do something.
name
Alarm
Mark
John
1
Eddie
1,2
Peter
1,2,3
What I need is to be able to put every value in a separate column or create a dropdown or something.
For example something like the table below or two drop down menus one to select the name and the other shows the alarms. (I prefer the drop downs).
name
Alarm
Mark
John
1
Eddie
1
2
Peter
1
2
3
Here I select Peter and the alarm drop down shows 3 alarms. or for Eddie it just shows 2 alarms and so on.
I read something about regex but I don't really understand how to put it to the test.
I found this online: (.+?)(?:,|$) but I don't know how to capture the output.
What I need is to be able to put every value in a separate column
Consider below approach
select * from (
select * except(alarm)
from your_table,
unnest(split(alarm)) flag with offset
)
pivot (min(flag) as alarm for offset in (0,1,2,3,4))
If applied to sample data in your question -output is

Custom Sort Order in CAML Query

How would one go about telling a CAML query to sort the results in a thoroughly custom order?
.
For instance, for a given field:
-- when equal to 'Chestnut' at the top,
-- then equal to 'Zebra' next,
-- then equaling 'House'?
Finally, within those groupings, sort on a second condition (such as 'Name'), normally ascending.
So this
ID Owns Name
————————————————————
1 Zebra Sue
2 House Jim
3 Chestnut Sid
4 House Ken
5 Zebra Bob
6 Chestnut Lou
becomes
ID Owns Name
————————————————————
6 Chestnut Lou
3 Chestnut Sid
5 Zebra Bob
1 Zebra Sue
2 House Jim
4 House Ken
In SQL, this can be done with Case/When. But in CAML? Not so much!
CAML does not have such a sort operator by my knowledge. The workaround might be that you add a calculated column to the list with a number datatype and formula
=IF(Owns="Chestnut",0,IF(Owns="Zebra",1,IF(Owns="House",3,999))).
Now it is possible to order on the calculated column, which translates the custom sort order to numbers. Another solution is that you create a second list with the items to own, and a second column which contains their sort order. You can link these two lists and order by the item list sort order. The benefit is that a change in the sort order is as easy as editing the respective listitems.

Hierarchical numbering in SQL result

I have a query that does a few full joins on some generally hierarchical data. Categories have Groups, and Groups have Items, though Groups and Items may be unattached to Categories and Groups, respectively. The results I'd like would look like this:
I. NULL
A. NULL
1. Item Orphan <-- no category or group
B. Group Red <-- no category
1. Item Apple
2. Item Banana
II. Category Bacon
A. Group Blue
B. Group Taupe
1. Item Kiwi
2. Item Watermelon
III. Category Atari
A. Group Silver
IV. Category Maui
...
Note: I added the periods after the numbering to make the example more readable, but the output needn't have them.
Right now the results look like this:
Category Group Item
NULL NULL Orphan
NULL Red Apple
NULL Red Banana
Bacon Blue NULL
Bacon Taupe Kiwi
Bacon Taupe Watermelon
Atari Silver NULL
Maui NULL NULL
And what I need is:
Co Category Go Group Io Item
I NULL A NULL 1 Orphan
I NULL B Red 1 Apple
I NULL B Red 2 Banana
II Bacon A Blue 1 NULL
II Bacon B Taupe 1 Kiwi
II Bacon B Taupe 2 Watermelon
III Atari A Silver 1 NULL
IV Maui A NULL 1 NULL
Although, the A on the last row and the 1s in the Io column on rows with NULL Items could also be NULLs. The I and the A on the Orphan Item row are important, though.
edit: This is simplified from the actual code for readability. In my case Items may have 0 or more Sub-items, so there may be multiple rows for each Item where the values for Co, Go, and Io would simply be duplicated. Sub-items aren't numbered though, so there's no ordinal column for them. So an example of some full rows would look like this:
Co Category Go Group Io Item Supplier Supplier_phone
I NULL B Red 2 Banana NULL NULL
II Bacon B Taupe 1 Kiwi Steve 555-1234
II Bacon B Taupe 1 Kiwi Sally 555-4242
II Bacon B Taupe 2 Watermelon NULL NULL
My problem is twofold:
how do I do the different numbering for each level of the hierarchy and have it increment whenever that level changes?
how do I translate those numbers into a different ordinal space (e.g. translate 1,2,3 into a,b,c or I,II,III) and do so on a per-level basis?
This is in MS SQL Server 2012. I only have access to SQL, so T-SQL code is out.
For reference, the FROM and WHERE clauses together in my query are about 20 lines of code that I'd like to keep DRY. I've used CTEs before, but I'm not sure if that would be useful in this case or not.
I'm familiar with using row_number over (order by..., but I don't see how I could use it in this case.
For the group numbers, I believe you want DENSE_RANK. It is used the same way as ROW_NUMBER, except for groups.
Without seeing your real code, it will be something like:
SELECT DENSE_RANK() over (ORDER BY Category) as Co,
Category,
DENSE_RANK() over (PARTITION BY Category, ORDER BY [Group]) as Go,
Group,
--etc
That said, I have no idea how you will convert numerics to numerals/letters without functions.

sql loader associating variable number physical records with a single physical record

I have the following data:
Aapple mango wood
Bpine tea orange
Bnuts blots match
Ajust another record
Now I want every record beginning with 'A' to be associated with record beginning with 'B' until another 'A' record or non-'B' record is encountered.
For example from the above data,
I would like to retrieve the following data(2 records),
mango tea
mango blots
The number of B records following an A record is variable, that is,(A record might be followed by any number of B records(3 in the data below).
Aapple mango wood
Bpine tea orange
Bnuts blots match
Basdf asdf asdf
Ajust another record
So the resulting output would be
mango tea
mango blots
mango asdf
Is it possible to do the above using sql loader?. Any help/pointers would be most welcome.
Edit:
I was thinking about using CONTINUEIF clause, but there doesn't seem to be way to eliminate the records that was retrieved earlier.
For example, if I use,
CONTINUEIF NEXT PRESERVE(1)='B'
I would get "mango tea blots asdf" in one go and not
"mango|tea"
"mango|blots"
"mango|asdf"
I think i would load the records to 2 seperate tables based on the record type identifier,
see: http://download.oracle.com/docs/cd/B19306_01/server.102/b14215/ldr_control_file.htm#i1005614
and use recnum to preserve the order
see: http://download.oracle.com/docs/cd/B10501_01/server.920/a96652/ch06.htm
you can then transform the data in sql
SELECT
a.text,
b.text,
a.id,
a.nxtid
FROM
(
SELECT text,id, NVL(LEAD(seq,1) OVER (ORDER BY id),999999) AS NXTID
FROM t1
) a
LEFT JOIN t2 B ON b.seq > a.id AND b.id < a.nxtid

custom sorting or ordering a table without resorting the whole shebang

For ten years we've been using the same custom sorting on our tables, I'm wondering if there is another solution which involves fewer updates, especially since today we'd like to have a replication/publication date and wouldn't like to have our replication replicate unnecessary entries.I had a look into nested sets, but it doesn't seem to do the job for us.
Base table:
id | a_sort
---+-------
1 10
2 20
3 30
After inserting:
insert into table (a_sort) values(15)
An entry at the second position.
id | a_sort
---+-------
1 10
2 20
3 30
4 15
Ordering the table with:
select * from table order by a_sort
and resorting all the a_sort entries, updating at least id=(2,3,4)
will of course produce the desired output:
id | a_sort
---+-------
1 10
4 20
2 30
3 40
The column names, the column count, datatypes, a possible join, possible triggers or the way the resorting is done is/are irrelevant to the problem.Also we've found some pretty neat ways to do this task fast.
only; how the heck can we reduce the updates in the db to 1 or 2 max.
Seems like an awfully common problem.
The captain obvious in me thougth once "use an a_sort float(53), insert using a fixed value of ordervaluefirstentry+abs(ordervaluefirstentry-ordervaluenextentry)/2".
But this would only allow around 1040 "in between" entries - so never resorting seems a bit problematic ;)
You really didn't describe what you're doing with this data, so forgive me if this is a crazy idea for your situation:
You could make a sort of 'linked list' where instead of a column of values, you have a column for the 'next highest valued' id. This would decrease the number of updates to a maximum of 2.
You can make it doubly linked and also have a column for next lowest, which would bring the maximum number of updates to 3.
See:
http://en.wikipedia.org/wiki/Linked_list