Inverting column data through a Query - sorting

In order to create a specific chart, I need to look for the values of column H in reverse to which they are presented. I tried via Query:
=QUERY(H2:J, "select H order by J desc", 0)
But it returned in the wrong way as you can see:
I would like to know what would need to be adjusted. Because did not return in the exact inverse sequence of column H as it should in theory happen.
Link to Spreadsheet:
https://docs.google.com/spreadsheets/d/1ehtyuyiAiuQvQUWgMrYBreUMA94jnAliu-VcHfBFi5s/edit?usp=sharing

try:
=ARRAYFORMULA(QUERY({ROW(H2:H), H2:H},
"select Col2
where Col2 is not null
order by Col1 desc", 0))

Related

Apache Pig: Filter one tuple on another?

I want to run a Pig script by splitting out two tuples (or whatever it's called in Pig), based off of criteria in col2, and after manipulating col2, into another column, compare the two manipulated tuples and do an additional exclude.
REGISTER /home/user1/piggybank.jar;
log = LOAD '../user2/hadoop_file.txt' AS (col1, col2);
--log = LIMIT log 1000000;
isnt_filtered = FILTER log BY (NOT col2 == 'Some value');
isnt_generated = FOREACH isnt_filtered GENERATE col2, col1, RANDOM() * 1000000 AS random, com.some.valueManipulation(col1) AS isnt_manipulated;
is_filtered = FILTER log BY (col2 == 'Some value');
is_generated = FOREACH is_filtered GENERATE com.some.calculation(col1) AS is_manipulated;
is_distinct = DISTINCT is_generated;
Splitting and manipulating is the easy part. This is where it gets complicated. . .
merge_filtered = FOREACH is_generated {FILTER isnt_generated BY (NOT isnt_manipulated == is_generated.is_manipulated)};
If I can figure out this line(s), the rest would fall in place.
merge_ordered = ORDER merge_filtered BY random, col2, col1;
merge_limited = LIMIT merge_ordered 400000;
STORE merge_limited into 'file';
Here's an example of the I/O:
col1 col2 manipulated
This qWerty W
Is qweRty R
An qwertY Y
Example qwErty E
Of qwerTy T
Example Qwerty Q
Data qWerty W
isnt
E
Y
col1 col2
This qWerty
Is qweRty
Of qwerTy
Example Qwerty
Data qWerty
I'm still not sure quite what you need, but I believe you can reproduce your input and output with the following (untested):
data = LOAD 'input' AS (col1:chararray, col2:chararray);
exclude = LOAD 'exclude' AS (excl:chararray);
m = FOREACH data GENERATE col1, col2, YourUDF(col2) AS manipulated;
test = COGROUP m BY manipulated, exclude BY excl;
-- Here you can choose IsEmpty or NOT IsEmpty according to whether you want to exclude or include
final = FOREACH (FILTER test BY IsEmpty(exclude)) GENERATE FLATTEN(m);
With the COGROUP, you group all tuples in each relation by the grouping key. If the bag of tuples from exclude is empty, it means that the grouping key was not present in the exclude list, so you keep tuples from m with that key. Conversely, if the grouping key was present in exclude, that bag will not be empty and the tuples from m with that key will be filtered out.

prevent full table scan

I have following query:
select id,
c1,
c2,
c3
from tbl t1
join
(select id
from tbl t2
where upper(replace(c5, ' ', '')) like upper(?)
) j
on j.id = t1.id
? is some wildcard parameter string like %test%.
c5 column has index on the function used to access it:
create index tbl_c5_idx on tbl(upper(replace(c5, ' ', '')))
When I run just inner query it uses tbl_c5_idx, however when I run the whole query it turns into full table scan which is much slower.
Are there any way to avoid full table scans? Hints or rewrite join condition. I can not rewrite whole query as inner query is constructed dynamically depending on the input conditions.
A very basic example to test your functionality
create table test(id number,value varchar2(200));
insert into test values(1,'gaurav is bad guy');
insert into test values(2,'gaurav is good guy');
SELECT *
FROM test
WHERE UPPER (REPLACE (VALUE, ' ', '')) LIKE UPPER ('%gauravisbad%');
before creating index this is doing a full table scan for obvious reason ,because no index get created.
create index tbl_c5_idx on test(upper(replace(value, ' ', '')));
The reason why i am asking you to avoid inner join on the same table because you're using the table twice once to get your records from your filter condition where your index are used and then join on the basis of id which is preventing of using index ,because you dont have index on id column,this can be done with a simple filter condition.
Please let me know if you're again finding out the same issue of full table scan ,or you're not getting the same result from this query .
if you're running the subquery only, it doesn't use the id column in the filters the way the parent query does, therefore the index can be used. In the parent query you are using the id as well, which prevents the index from being used. Maybe adding an index on (id, upper(replace(c5, ' ', ''))) would solve the problem.
Gaurav Soni is right: you don't need a subquery to achieve your goal.
always check performances rather than the explain plan. Performances might just be worst with your hint than without. Oracle is NOT stupid.
Seems I found solution, or at least a thing that helps.
I used index hint, so access is done with tbl_c5_idx.
That is how final query looks now:
select /*+ index(t1) */ id,
c1,
c2,
c3
from tbl t1
join
(select id
from tbl t2
where upper(replace(c5, ' ', '')) like upper(?)
) j
on j.id = t1.id

How to make sort case insensitive while displaying the lower+upper case of values in the dropdown

I am trying to convert my query result to and order them according to lowercase in asc order. But while displaying I need to preserve all the original case (lower and upper case).
My query looks like this -
SELECT distinct (p.product_id) as product_id ,lcase(p.product_name) as product_name
from library TL, product p
WHERE TL.id = PL.id
AND pL.product_id = p.product_id
AND pL.product_id NOT IN (0)
order by lcase(product_name) asc;
But when I display it changes the entire dropdown values to lowercase. This is not what i want. I just want it to be displaying according to the order by lowercase.
How can I do it?
As far as I know, my orderby should have the same condition as the select isnt it?
How to make sort case insensitive while displaying the lower+upper case of values in the dropdown
You can try this,
SELECT product_id, product_name FROM (
SELECT distinct (p.product_id) as product_id ,(p.product_name) as product_name,
lcase(p.product_name) as pname
from unified.techlibrary TL, unified.techlibraryprod PL, unified.product p, unified.contenttype CT
WHERE TL.id = PL.id
AND pL.product_id = p.product_id
AND tl.contenttype_id in (1,3)
AND pL.product_id NOT IN (0)
) AS x order by x.pname
Hope it will help.

Oracle: MIN() Statement causes empty row returns

I'm having a small issue with sorting the data returned from a query, with the aim of getting the oldest updated value in dataset so that I can update only that record. Here's what I'm doing:
WHERE ROWNUM = 1 AND TABLE1.ID != V_IGNOREID
AND TABLE1.LASTREADTIME = (SELECT MIN(TABLE1.LASTREADTIME) FROM TABLE1)
ORDER BY TABLE1.LASTREADTIME DESC;
It makes no difference as to whether the ORDER BY statement is included or not. If I only use the ROWNUM and equality checks, I get data, but it alternates between only two rows, which is why I'm trying to use the LASTREADTIME data (so that I can modify more than these two rows). Anybody have any thoughts on this, or any suggestions as to how I can use the MIN function effectively?
Cheers
select * from (
-- your original select without rownum and with order by
)
WHERE ROWNUM = 1
EDIT some explanation
I think the order by clause is applied on the resultset after the where clause. So if the rownum = 1 is in the same select statement with the order by, then it will be applied first and the order by will order only 1 row, which will be the first row of the unordered resultset.

how to get alphabetically next and prev records wiht minimal fetched records?

I have a page that is displaying a company name and its details from a table A.
Now say i have a company displayed,and its name is 'Company_one' now i want to have alphabetically sorted next company and previous company and their details etc.
The data in my table is not sorted.Its stored as it gets the data.
So now what kind of query should i write that it gives only one previous and one next alphabetically sorted record??
Plz help!!
There's no nice way to do that in a single query. Just do two queries.
To get the previous one:
SELECT * FROM companies
WHERE name < variable_with_current_name
ORDER BY name DESC
LIMIT 1
To get the next one along:
SELECT * FROM companies
WHERE name > variable_with_current_name
ORDER BY name ASC
LIMIT 1
You need to use the sort clause to sort your table. The prototype for sort is:
sort by fieldname
Example Query:
select * from your_table sort by company asc
If you want to limit records, use limit clause:
select * from your_table sort by company asc limit 0, 1
Based on Dominic's answer, you can achieve the same result using a single query by combining them with WHERE and OR.
For example:
SELECT * FROM `companies`
WHERE (
`name` = IFNULL(
(SELECT `name` FROM `companies`
WHERE `name` < 'variable_with_current_name'
ORDER BY `name` DESC
LIMIT 1)
, 0)
OR
`name` = IFNULL(
(SELECT `name` FROM `companies`
WHERE `name` > 'variable_with_current_name'
ORDER BY `name` ASC
LIMIT 1)
, 0)
)
Hope that helps.

Resources