I have table with 3 columns A B C.
I want to select * from this table, but ordered by a specific ordering of column A.
In other words, lets' say column A contains "stack", "over", "flow".
I want to select * from this table, and order by column A in this specific ordering: "stack", "flow", "over" - which is neither ascending nor descending.
Is it possible?
You can use a CASE statement in the ORDER BY clause. For example ...
SELECT *
FROM Table
ORDER BY
CASE A
WHEN 'stack' THEN 1
WHEN 'over' THEN 2
WHEN 'flow' THEN 3
ELSE NULL
END
Check out Defining a Custom Sort Order for more details.
A couple of solutions:
Create another table with your sort order, join on Column A to the new table (which would be something like TERM as STRING, SORTORDER as INT). Because things always change, this avoids hard coding anything and is the solution I would recommend for real world use.
If you don't want the flexibility of adding new terms and orders, just use a CASE statement to transform each term into an number:
CASE A WHEN 'stack' THEN 1 WHEN 'over' THEN 2 WHEN 'flow' THEN 3 END
and use it in your ORDER BY.
If you have alot of elements with custom ordering, you could add those elements to a table and give them a value. Join with the table and each column can have a custom order value.
select
main.a,
main.b,
main.c
from dbo.tblMain main
left join tblOrder rank on rank.a = main.a
order by rank.OrderValue
If you have only 3 elements as suggested in your question, you could use a case in the order by...
select
*
from dbo.tblMain
order by case
when a='stack' then 1
when a='flow' then 2
when a='over' then 3
else 4
end
Related
once i run first query i got the below result:
REQUEST_NO R
---------- -
4309300 A
4300983 C
and i want to compare if R column is different to "C" run second query and do the same for each element that i can have in REQUEST_NO column different to C
SELECT REQUEST_NO
, REQUEST_STS
FROM PORT_REQUEST
WHERE REQUEST_NO IN (SELECT DISTINCT REQUEST_NO
FROM SUB_PORT_REQUEST
WHERE SUBSCRIBER_NO = replace(replace('&CTN','-',''),' ',''));
Enter value for ctn: 5161890110
REQUEST_NO R
---------- -
4309300 A
4300983 C
SELECT ACT_SEQ_NO
FROM SUB_PORT_REQUEST
WHERE REQUEST_NO=&Req_No
AND ROWNUM <=1
ORDER BY ACT_SEQ_NO DESC;
Enter value for req_no: 4309300
ACT_SEQ_NO
----------
91180671
I expect to save in a array or something all values and can be able to iterate on it, can someone help?
One option, if you want to remain in SQL*Plus, is to create a (global temporary?) table, store result of the first query into it, and then rewrite the second query to use those results as
where request_no in (select request_no from my_temporary_table)
Another is to switch to PL/SQL and write a procedure which will accept CTN as a parameter. It (PL/SQL) allows you to use different ways to store results of the first query - into a table (as previously) or an array.
You can combine these to just 1 query by joining the tables. I am not sure I know how to handle the segment "and rownum<=1 Order by ...". Either the order by clause is not needed as rownum<=1 will produce at most 1 row and no matter how you sort it 1 row always comes out the same. Or you expect multiple rows want only want the greatest act_seq_no. If that is the case you need the order by in a sub-query and the rownum predicate on the outer. Assuming the latter we get:
Also assuming the column you refer to as R in description is actually the column port_request.request_sts as R is NOT selected nor is it an alias for any referenced column given.
select act_seq_no
from ( select spr.act_seq_no
from sub_port_request spr
join port_request pr
on (spr.request_no = pr.request_no and
pr.request_sts != 'C'
)
where spr.subscriber_no = replace(replace('&CTN','-',''),' ','')
order by spr.act_seq_no desc
)
where rownum<=1;
I am trying to sort data by applying case when statement in the order by clause but looks like Big Query doesn't support even though it worked fine in other SQL environments. Can somebody share your thoughts on this.
Update (2021) - Bigquery now does support ORDER BY with expressions, e.g.
SELECT event_type, COUNT(*) as event_count
FROM events
GROUP BY event
ORDER BY (
CASE WHEN event='generated' THEN 1
WHEN event='sent' THEN 2
WHEN event='paid' THEN 3
ELSE 4
END
)
select x
from (
select x ,
case when x = 'a' then 'z' else x end as y
from
(select 'a' as x),
(select 'b' as x),
(select 'c' as x),
(select 'd' as x)
)
order by y desc
I think the documentation is pretty clear:
ORDER BY clause
... ORDER BY field1|alias1 [DESC|ASC], field2|alias2 [DESC|ASC] ...
The ORDER BY clause sorts the results of a query in ascending or
descending order of one or more fields. Use DESC (descending) or ASC
(ascending) to specify the sort direction. ASC is the default.
You can sort by field names or by aliases from the SELECT clause. To
sort by multiple fields or aliases, enter them as a comma-separated
list. The results are sorted on the fields in the order in which they
are listed.
So, BigQuery doesn't allow expressions in the ORDER BY. However, you can include the expression in the SELECT and then refer to it by the alias. So, BigQuery does support "custom sorting", but only by expressions in the SELECT.
Interestingly, Hive has a similar limitation.
I want to retrieve a full table with some of the values sorted. The sorted values should all appear before the unsorted values. I though I could pull this off with a UNION but order by is only valid to use after unioning the table and my set of data isn't set up such that that is useful in this case. I want rows with a column value of 0-6 to show up sorted in DESC order and then the rest of the results to show up after that. Is there some way to specify a condition in the order by clause? I saw something that looked close to what I wanted to so but I couldn't get the equality condition working in sql. I'm going to try to make a query using WHEN cases but I'm not sure if there's a way to specify a case like currentValue <= 6. If anyone has any suggestions that would be awesome.
You could do something like this:
order by (case when currentValue <= 6 then 1 else 0 end) desc,
(case when currentValue <= 6 then column end) desc
The first puts the values you care about first. The second puts them in sorted order. The rest will be ordered arbitrarily.
Try this:
SELECT *
FROM yourdata
ORDER BY CASE WHEN yourColumn BETWEEN 0 AND 6 THEN yourColumn ELSE -1 End Desc
One RDBMS-agnostic solution would be to add a second field that takes the same value as the field you wish to sort when that field is less than or equal to six. Then just sort by that field.
I have the below query. The problem is the last column productdesc is returning two records and the query fails because of distinct. Now i need to add one more column in where clause of the select query so that it returns one record. The issue is that the column i need
to add should not be a part of group by clause.
SELECT product_billing_id,
billing_ele,
SUM(round(summary_net_amt_excl_gst/100)) gross,
(SELECT DISTINCT description
FROM RES.tariff_nt
WHERE product_billing_id = aa.product_billing_id
AND billing_ele = aa.billing_ele) productdescr
FROM bil.bill_sum aa
WHERE file_id = 38613 --1=1
AND line_type = 'D'
AND (product_billing_id, billing_ele) IN (SELECT DISTINCT
product_billing_id,
billing_ele
FROM bil.bill_l2 )
AND trans_type_desc <> 'Change'
GROUP BY product_billing_id, billing_ele
I want to modify the select statement to the below way by adding a new filter to the where clause so that it returns one record .
(SELECT DISTINCT description
FROM RRES.tariff_nt
WHERE product_billing_id = aa.product_billing_id
AND billing_ele = aa.billing_ele
AND (rate_structure_start_date <= TO_DATE(aa.p_effective_date,'yyyymmdd')
AND rate_structure_end_date > TO_DATE(aa.p_effective_date,'yyyymmdd'))
) productdescr
The aa.p_effective_date should not be a part of GROUP BY clause. How can I do it? Oracle is the Database.
So there are multiple RES.tariff records for a given product_billing_id/billing_ele, differentiated by the start/end dates
You want the description for the record that encompasses the 'p_effective_date' from bil.bill_sum. The kicker is that you can't (or don't want to) include that in the group by. That suggests you've got multiple rows in bil.bill_sum with different effective dates.
The issue is what do you want to happen if you are summarising up those multiple rows with different dates. Which of those dates do you want to use as the one to get the description.
If it doesn't matter, simply use MIN(aa.p_effective_date), or MAX.
Have you looked into the Oracle analytical functions. This is good link Analytical Functions by Example
I have the following query:
SELECT a.field_eventid_key_value, a.field_showdate_value, b.nid , c.nid AS CNID
FROM content_type_vorfuehrung AS a
LEFT JOIN content_type_movies as b ON a.field_eventid_key_value = b.field_eventid_value
LEFT JOIN content_type_sonderveranstaltung as c ON a.field_eventid_key_value = c.field_sonderveranstaltungid_value
WHERE /* something */
GROUP BY a.field_eventid_key_value, a.field_showdate_value,
ORDER BY a.field_showdate_value ASC,a.field_showtime_value ASC
(where clause removed since it's irrelevant to the question)
This pulls data from 3 different tables and sorts it according to the "showdate" field in the first table. This is used in a PHP function that returns an array with the results.
Now there is a new requirement: The table "content_type_movies" in this query has a field that's supposed to be a boolean (actually it's an int with a value of either "0" oder "1"). This field is supposed to override the chronological ordering - that is, results where the field is "true" (or "1" respectively) should appear at the beginning of the result array (with the remaining entries ordered chronologically as before).
Is this at all possible with a single query ?
Thank you in advance for your time,
eike
You can use:
ORDER BY b.MyIntField DESC,
a.field_showdate_value,
a.field_showtime_value
where MyIntField is the field that is either 1 or 0 that you want to sort first.
ORDER BY a.content_type_movies DESC, /*then other fields*/ a.field_showdate_value ASC,a.field_showtime_value ASC
that should place all rows with content_type_movies=1 first then others.